[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, master, updated. debian/0.24.5-2-95-g543fd9d

Micah Anderson micah at riseup.net
Thu Nov 27 19:59:47 UTC 2008


The following commit has been merged in the master branch:
commit 543fd9ddaa7c96510f593361986c377d6c4a3bf8
Author: Micah Anderson <micah at riseup.net>
Date:   Thu Nov 27 14:58:37 2008 -0500

    Revert "Imported Upstream version 0.24.6"
    
    This reverts commit 4a78bb39c1b18d81890832892dafa4b89aed897e.

diff --git a/CHANGELOG b/CHANGELOG
index d3a2ef2..b5326a1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,344 +1,3 @@
-0.24.6
-    Adding support to the user type for: profiles, auths, project, 
-    key/value pairs (extension to Solaris RBAC support added in
-    0.24.6)
-
-    Fixed #1662 - Configuration Reference still references 'section'
-
-    Fixed #1460 - enhance redhat puppetmaster init.d script to easy start puppetmaster as a mongrel cluster
-
-    Fixed #1663 - Regression relating to facter fact naming from 0.24.5
-
-    Fixed #1655 - Provider::Confine::Variable tests are broken
-
-    Fixed #1646 - service puppet status does not work as non-root 
-    on redhat system
-
-    Fixed #1649 - Updated OSX package cleanup
-  
-    Fixed #1647 - puppetdoc -r providers now working again
-
-    Fixed #1639 - uninitialized constant Puppet::Type::User::ProviderUseradd
-
-    Fixed #1637 - With an inexistant (global) templatedir, modules 
-    can't access their templates
-
-    Fixed #1202 - Collection attribute matching doesn't parse arrays
-
-    Fixed #1473 - Puppetd stops with error after puppetmasterd 
-    is unavailable
-
-    Fixed #1354 - yum provider problems with RHEL 3
-
-    Fixed #1633 - Added support for --detailed-exits to bin/puppet
-
-    Fixed #381 - Allow Allow multiple overrides in one statement
-
-    Fixing #947 - pluginsync no longer fails poorly when no plugins exist
-
-    Fixed #981 - Removed 'Adding aliases' info message
-    
-    Fixing #1089 - Log messages are now tagged with the log level,
-    making it easier to match messages in the 'tagmail' report.
-    
-    Fixing #1098 - Multiline strings now correctly increment the line count
-
-    Fixing #1614 - Environments no longer have to be listed out
-
-    Fixed #1628 - Changed node search to use certname rather than Facter 
-    hostname
-    
-    Fixed #1613 - The client environment will be substituted when looking 
-    up settings.
-
-    Updated puppet binary documentation 
-
-    Feature #1624 - Added RBAC roles to solaris user provider
-
-    Fixed #1586 - Specifying "fully qualified" package names in Gentoo
-
-    Fixed #1620 - Add 'sles' to Puppet confines when 'suse' is used
-
-    Fixed #1585 - Allow complex 'if' and variable expressions
-
-    Fixed #1564 - Saving File#checksum to state.yaml broken
-
-    Fixed #1603 - Added support for running Puppet inside a Rack application
-    (mod_rails) with Passenger and Apache
-
-    Fixed #1596 - Deploying file resources with ++ generates error
-
-    Modified the group and zone resource types to no longer call
-    'currentpropvalues' as a means of setting all values to absent.
-    There should be no behaviour change from this change.
-
-    Modified the behaviour of resource-level 'retrieve' -- it only
-    calls 'retrieve' on each property if the resource exists.
-
-    Fixed #1622 - Users and their groups should again add in one transaction
-
-    Fixed #791 - You should now be able to create and find a user/group in one transaction.
-
-    Fixed #1610 - Raise "Filebucketed" messages to Notice priority
-    
-    FIxed #1530 - ssh_authorized_keys provider does not crash anymore on SSH type 1 keys
-
-    Added a number of confines to package providers
-
-    Fixed #1609 - Added confines for the Gentoo, FreeBSD and 
-    SMF (Solaris) service providers 
-
-    Fixed #1608 - Added ubuntu to defaultfor for apt provider
-
-    Fixed #1607 - Added ubuntu to defaultfor for Debian service
-    provider
-
-    Fixed #1045 - Multiple metaparams all get added to resources.
-    
-    Fixed #1472 -- defined, exported resources in the current compile 
-    now get expanded correctly.
-
-    Fixed #1595 - Internally, Property#retrieve is no longer called
-    when no 'should' value is available for a resource.
-
-    Fixed #1588 - Fixed puppetca --clean --all 
-
-    Fixed #1584 - Added support for appended variables
-
-    Fixed #1554 - Added support for multiple template directories
-
-    Fixed #1500 - puppetrun not working
-
-    Fixed #1579 and #1580 - errors in the Puppet RPM spec file
-
-    Fixed #1572 -- file purging now fails if remote sources do not exist.
-    
-    Fixed #1521 -- ldap user and password are now used with the default connection.
-
-    Fixed issues with file descriptors leaking into subprocesses
-
-    Fixed #1568 - createpackage.sh
-
-    Fixed #1571 - Puppet::Util::binary returns incorrect results
-
-    Fixed #1553 - Puppet and Facter cannot both install the plist module into two different locations
-
-    Adjusted hpuxuseradd user provider to confine to HP-UX and fixed HP-UX user provider path regression
-
-    Fixed debug messages in package type - thanks to Todd Zullinger for this fix
-    
-    Fixed #1566 - changed password property of the user type
-
-    Fixed debug messages in package type
-
-    Updated Red Hat spec file
-
-    Fixes #1455 - Adds HP-UX support for user type
-
-    Fixes #1551 puppetmaster.freshness xmlrpc call returns incorrect type
-
-    Fixes #1554 - Fix exception for undefined hostname
-
-    Fixed #1533 - changed permissions for man directory
-
-    Added daemontools and runit providers for service type
-
-    Added simple rake task for running unit tests
-
-    Added spec Rake task
-
-    Fixed #1526 - Fixed leak in template
-
-    Fixed #1506 - Removed storeconfig duplicate indexes
-    
-    Fixed #1457 - case insensitive match for error
-    
-    Fixed #1488 - Moved individual functions out of functions.rb into 
-    lib/puppet/parser/functions directory.  New functions should be create     in this directory.
-
-    Fixed #1508 - Added HP-UX package provider
-
-    Fixed #1502 - Fixed poor stored configuration performance
-
-    Fixed #1510 - Storeconfiguration fixed for Rails 2.1
-
-    Add the -P/--ping option to puppetrun, fixes #1501
-
-    Fixed #1394 - Added stored configuration clearing script to /ext
-    
-    Fixed #1442 - replaced use of Facter for report titling with certname
-
-    Fixed $1456 - add proxy configuration capability to yum repo
-
-    Fixed #1457 - removed confine warning
-
-    A working script to create an OS X pkg out of the Puppet repository
-
-    Fixed #1441 - Updated console colours
-
-    Expose all puppet variables as instance member variables of the template wrapper.
-    This helps resolve redmine #1427, by providing a safe mechanism to access variables.
-    
-     * Implement Puppet::Parser::Scope#to_hash, which returns a hash containing all the
-       variable bindings in the current and, optionally, parent scope.
-     * Use that to set instance member variables into Puppet::Parser::Templatewrapper
-     * Report the time taken for variable binding at debug level, to help identify any
-       performance regression that is encountered in the real world.
-     * Rename the @scope and @file members of the template wrapper, to avoid clashing
-       with a scope variable exposed within puppet.
-
-    Ensure that we consistently use either string #{} interpolation or String.%
-    interpolation, not both, to avoid issues where a #{} interpolated value
-    contains a % character.
-
-    Feature #1476: Allow specification of --bindir --sbindir --sitelibdir --mandir --destdir 
-    in installation
-    
-    Added feature #1241 : Improve performance of group lookups
-
-    Fixed bug #1448: Puppet CA incorrectly writes out all certs to inventory .txt on each 
-    certificate signing
-
-    Fixing puppetlast to make it work with 0.24.5 / 0.25.  Made puppetlast work on 0.24.5 
-    by using the YAML indirector
- 
-0.24.5
-    You can now select the encoding format when transferring the catalog,
-    with 'yaml' still being the default but 'marshal' being an option.
-    This is because testing has shown drastic performance differences
-    between the two, with up to 70% of compile time being spent
-    in YAML code.  Use the 'catalog_format' setting to choose your format,
-    and the setting must be set on the client.
-
-    Fixed #1431 - Provider confines must now specify similar tests in one call.
-    I.e., you can't do confine :operatingsystem => %w{a b} and then
-    confine :operatingsystem => %w{b c}; you'd need to do them in one command.
-    This now-obsolete behaviour does not seem to be used anywhere.
-    The fix for #1431 is actually just removing the tests that exposed
-    this change; the change happened when I refactored how confines work.
-
-    Removed faulty interface type
-
-    Updated /spec/unit/rails.rb test
-
-    Fix #1426 - services on redhat are restarted again and status is 
-    called from the Red Hat provider
-
-    Fixed #1414 - Return code from waitpid now right shifted 8 bits
-
-    Fixed #174 - a native type type for managing ssh authorized_keys 
-    files is available.
-
-    Further moves from the examples directory and ext directory
-
-    Fixed #1397 One line fix, fail instead of log
-
-    Moved debian to conf and updated examples directory
-
-    Fixed #1368 - updated Red Hat init scripts
- 
-    Added message referencing ReductiveLabs build library
-
-    Fixed #1396 - Added sha1 function from DavidS to core
-    
-    Fixed #1399 - the ldap user provider now knows it can manage
-    passwords.
-    
-    Fixed #1272 - if you provide a group name as the gid to an ldap
-    user, the name will be converted to a gid.  Note that this only
-    looks up ldap groups, at this point; if you want to set an ldap
-    user's primary group to a local group, you have to specify the GID.
-
-    Fixed #1226 - gems can now specify source repositories.
-
-    Fixed #1232 - the rundir no longer specifies a user/group,
-    and there are now client- and server-specific yaml directories.
-
-    Fixed 1240 - puppet will function more like puppetd if graphing
-    or reporting are enabled.
-    
-    Fixed #1231 - Exceptions during initialization should now be clearer.
-
-    Fixed #1006 - puppetrun --class works again.  I added the class
-    membership testing to the Ldap node terminus, and added tests,
-    so it shouldn't break again.
-
-    Fixed #1114 - Facts in plugin directories should now be autoloaded,
-    as long as you're using Facter 1.5.
-
-    Fixed #1195 - Updated Gentoo init scripts
-
-    Fixed #1367 - Updated Rakefile for new daily builds
-
-    Fixed #1370 - removed test/util/loadedfile.rb tests
-    
-    Fixed #1221 - aliases to titles now work for resources.
-    
-    Fixed #1012 - templates in the templatedir are preferred to module templates.
-
-    Fixed #707 - special '@reboot'-style cron jobs work again.
-
-    Fixed #1360 - allowdupe works on groups again.
-
-    Fixed #1369 - the init service provider now supports HP-UX.
-
-    Removed support for the 'node_name' setting in LDAP and external node 
-    lookups.
-
-    Also removed support for 'default' nodes in external nodes.
-    LDAP nodes now use the certificate name, the short name, and 'default',
-    but external nodes just use the certificate name and any custom terminus
-    types will use just the certificate name.
-    
-    Fixing #1168 (for 0.24.x) -- automatically downcasing the fqdn.
-    Also requiring that passed in certnames be downcased; the setting
-    system isn't currently flexible enough to automatically downcase
-    it for the user.
-
-    Adding a ResourceTemplate class for using templates directly
-    within resources (i.e., client-side templates).  This would really
-    only be used for composite resources that pass the results of the
-    template on to generated resources.
-
-    Exporting or collecting resources no longer raises an exception
-    when no storeconfigs is enabled, it just produces a warning.
-
-    Always using the cert name to store yaml files, which fixes #1178.
-    The Master handler previously provided the support for the :node_name
-    setting, and that functionality has now been moved into the Node
-    class.  At the same time, the names to search through have been
-    changed somewhat:  Previously, the certificate name and the 
-    hostname were both used for searching, but now, the cert name
-    is always searched first (unless node_name == facter), but only
-    the Facter hostname, domain, and fqdn are used otherwise.  We no
-    longer split the cert name, only the hostname/domain/fqdn.
-
-    Fixing transaction support for prefetching generated resources.
-
-    Adding support for settings within the existing Facter provider confines.
-
-    Moving all confine code out of the Provider class, and fixing #1197. 
-    Created a Confiner module for the Provider class methods, enhanced 
-    the interface between it and the Confine class to make sure binary 
-    paths are searched for fresh each time.
-
-    Modified the 'factpath' setting to automatically configure
-    Facter to load facts there if a new enough version of
-    Facter is used.
-
-    Crontab provider: fix a parse error when a line begins with a space 
-    character (fixes #1216)
-
-    Instead of deleting the init scripts (with --del) we should simply 
-    disable it with chkconfig service off, and respectfully do the same 
-    for enable => true;
- 
-    Added ldap providers for users and groups.
-
-    Added support for the --all option to puppetca --clean.  If
-    puppetca --clean --all is issued then all client certificates
-    are removed.
- 
     Resources now return the 'should' value for properties from
     the [] accessor method (they previously threw an exception when
     this method was used with properties).  This shouldn't have any
diff --git a/Rakefile b/Rakefile
index 45d3652..1a3faad 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ $: << File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
 begin
     require 'rake/reductive'
 rescue LoadError
-    $stderr.puts "You must have the Reductive build library in your RUBYLIB; see http://github.com/lak/reductive-build/tree/master."
+    $stderr.puts "You must have the Reductive build library in your RUBYLIB."
     exit(14)
 end
 
@@ -23,7 +23,7 @@ project = Rake::RedLabProject.new("puppet") do |p|
         'lib/puppet.rb',
         'lib/puppet/**/*.rb',
         'lib/puppet/**/*.py',
-        'test/**/*',
+        'test/**/*.rb',
         'bin/**/*',
         'ext/**/*',
         'examples/**/*',
@@ -60,7 +60,6 @@ if project.has?(:gem)
             '--main' << 'README' <<
             '--line-numbers'
         task.test_file = "test/Rakefile"
-        task.author = "Luke Kanies"
     end
 end
 
@@ -103,7 +102,7 @@ def daily(package)
     edir = "/tmp/daily-export"
     Dir.mkdir edir
     Dir.chdir(edir) do
-        sh %{git clone git://reductivelabs.com/#{package} #{package} >/dev/null}
+        sh %{svn export http://reductivelabs.com/svn/#{package}/trunk #{package} >/dev/null}
         sh %{tar cf - #{package} | gzip -c > #{dailyfile(package)}}
     end
     FileUtils.rm_rf(edir)
@@ -144,56 +143,3 @@ task :tracdocs do
         sh "puppetdoc -m trac -r #{ref.to_s}"
     end
 end
-
-desc "Run the specs under spec/"
-task :spec do
-    require 'spec'
-    require 'spec/rake/spectask'
-    require 'rcov'
-    Spec::Rake::SpecTask.new do |t|
-         #   t.rcov = true
-         t.spec_opts = ['--format','s', '--loadby','mtime']
-         t.spec_files = FileList['spec/**/*.rb']
-    end
-end
-
-desc "Run the unit tests"
-task :unit do
-    sh "cd test; rake"
-end
-
-desc "Send patch information to the puppet-dev list"
-task :mail_patches do
-    if Dir.glob("00*.patch").length > 0
-        raise "Patches already exist matching '00*.patch'; clean up first"
-    end
-
-    unless %x{git status} =~ /On branch (.+)/
-        raise "Could not get branch from 'git status'"
-    end
-    branch = $1
-    
-    unless branch =~ %r{^([^\/]+)/([^\/]+)/([^\/]+)$}
-        raise "Branch name does not follow <type>/<parent>/<name> model; cannot autodetect parent branch"
-    end
-
-    type, parent, name = $1, $2, $3
-
-    # Create all of the patches
-    sh "git-format-patch -C -M -s -n #{parent}..HEAD"
-
-    # And then mail them out.
-
-    # If we've got more than one patch, add --compose
-    if Dir.glob("00*.patch").length > 1
-        compose = "--compose"
-    else
-        compose = ""
-    end
-
-    # Now send the mail.
-    sh "git send-email #{compose} --no-chain-reply-to --no-signed-off-by-cc --suppress-from --no-thread --to puppet-dev at googlegroups.com 00*.patch"
-
-    # Finally, clean up the patches
-    sh "rm 00*.patch"
-end
diff --git a/autotest/discover.rb b/autotest/discover.rb
new file mode 100644
index 0000000..0ac5637
--- /dev/null
+++ b/autotest/discover.rb
@@ -0,0 +1,9 @@
+require 'autotest'
+
+Autotest.add_discovery do
+  "rspec"
+end
+
+Autotest.add_discovery do
+  "puppet"
+end
diff --git a/autotest/puppet_rspec.rb b/autotest/puppet_rspec.rb
new file mode 100644
index 0000000..5ff794e
--- /dev/null
+++ b/autotest/puppet_rspec.rb
@@ -0,0 +1,60 @@
+require 'autotest'
+require 'autotest/rspec'
+
+Autotest.add_hook :initialize do |at|
+    at.clear_mappings
+
+    # the libraries under lib/puppet
+    at.add_mapping(%r%^lib/puppet/(.*)\.rb$%) { |filename, m|
+        at.files_matching %r!spec/(unit|integration)/#{m[1]}.rb!
+    }
+
+    # the actual spec files themselves
+    at.add_mapping(%r%^spec/(unit|integration)/.*\.rb$%) { |filename, _|
+        filename
+    }
+
+    # force a complete re-run for all of these:
+
+	# main puppet lib
+	at.add_mapping(%r!^lib/puppet\.rb$!) { |filename, _|
+        at.files_matching %r!spec/(unit|integration)/.*\.rb!
+	}
+
+	# the spec_helper
+	at.add_mapping(%r!^spec/spec_helper\.rb$!) { |filename, _|
+        at.files_matching %r!spec/(unit|integration)/.*\.rb!
+	}
+
+	# the puppet test libraries
+	at.add_mapping(%r!^test/lib/puppettest/.*!) { |filename, _|
+        at.files_matching %r!spec/(unit|integration)/.*\.rb!
+	}
+
+        # the puppet spec libraries
+	at.add_mapping(%r!^spec/lib/spec.*!) { |filename, _|
+        at.files_matching %r!spec/(unit|integration)/.*\.rb!
+	}
+
+        # the monkey patches for rspec
+	at.add_mapping(%r!^spec/lib/monkey_patches/.*!) { |filename, _|
+        at.files_matching %r!spec/(unit|integration)/.*\.rb!
+	}
+end
+
+class Autotest::PuppetRspec < Autotest::Rspec
+  # 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('vendor', 'gems', 'rspec', 'bin', 'spec') ,
+      File.join('bin', 'spec'),
+      File.join(Config::CONFIG['bindir'], 'spec')
+    ]
+  end
+
+end
diff --git a/autotest/rspec.rb b/autotest/rspec.rb
new file mode 100644
index 0000000..ebafbfe
--- /dev/null
+++ b/autotest/rspec.rb
@@ -0,0 +1,74 @@
+require 'autotest'
+
+Autotest.add_hook :initialize do |at|
+  at.clear_mappings
+  # watch out: Ruby bug (1.8.6):
+  # %r(/) != /\//
+  at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _| 
+    filename 
+  }
+  at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| 
+    ["spec/#{m[1]}_spec.rb"]
+  }
+  at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) { 
+    at.files_matching %r{^spec/.*_spec\.rb$}
+  }
+end
+
+class RspecCommandError < StandardError; end
+
+class Autotest::Rspec < Autotest
+
+  def initialize
+    super
+
+    self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m
+    self.completed_re = /\Z/ # FIX: some sort of summary line at the end?
+  end
+
+  def consolidate_failures(failed)
+    filters = Hash.new { |h,k| h[k] = [] }
+    failed.each do |spec, failed_trace|
+      if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } then
+        filters[f] << spec
+        break
+      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(separator=File::ALT_SEPARATOR)
+    unless defined? @spec_command then
+      @spec_command = spec_commands.find { |cmd| File.exists? cmd }
+
+      raise RspecCommandError, "No spec command could be found!" unless @spec_command
+
+      @spec_command.gsub! File::SEPARATOR, separator if separator
+    end
+    @spec_command
+  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.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')),
+      File.join(Config::CONFIG['bindir'], 'spec')
+    ]
+  end
+end
diff --git a/bin/filebucket b/bin/filebucket
index 17e01ed..5790c94 100755
--- a/bin/filebucket
+++ b/bin/filebucket
@@ -163,9 +163,8 @@ end
 # Now parse the config
 Puppet.parse_config
 
-if Puppet.settings.print_configs?
-        exit(Puppet.settings.print_configs ? 0 : 1)
-end
+Puppet.genconfig
+Puppet.genmanifest
 
 begin
     if options[:local] or options[:bucket]
diff --git a/bin/pi b/bin/pi
new file mode 100755
index 0000000..0b700a2
--- /dev/null
+++ b/bin/pi
@@ -0,0 +1,234 @@
+#!/usr/bin/env ruby
+
+#
+# = Synopsis
+#
+# Print help about puppet types on the console. Run with '-h' to get detailed
+# help.
+#
+
+# FIXME: (1) Formatting could be a lot prettier
+#        (2) The command line options are kinda screwy; unclear how best to
+#            present the various pieces of info to user
+
+require 'puppet'
+require 'optparse'
+
+class Formatter
+
+    def initialize(width)
+        @width = width
+    end
+
+    def wrap(txt, opts)
+        return "" unless txt && !txt.empty?
+        work = (opts[:scrub] ? scrub(txt) : txt)
+        indent = (opts[:indent] ? opts[:indent] : 0)
+        textLen = @width - indent
+        patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
+        prefix = " " * indent
+
+        res = []
+
+        while work.length > textLen
+            if work =~ patt
+                res << $1
+                work.slice!(0, $&.length)
+            else
+                res << work.slice!(0, textLen)
+            end
+        end
+        res << work if work.length.nonzero?
+        return prefix + res.join("\n" + prefix)
+    end
+
+    def header(txt, sep = "-")
+        "\n#{txt}\n" + sep * txt.size
+    end
+
+    private
+
+    def scrub(text)
+        # For text with no carriage returns, there's nothing to do.
+        if text !~ /\n/
+            return text
+        end
+        indent = nil
+
+        # If we can match an indentation, then just remove that same level of
+        # indent from every line.
+        if text =~ /^(\s+)/
+            indent = $1
+            return text.gsub(/^#{indent}/,'')
+        else
+            return text
+        end
+    end
+
+end
+
+class TypeDoc
+    
+    def initialize
+        @format = Formatter.new(76)
+        @types = {}
+        Puppet::Type.loadall
+        Puppet::Type.eachtype { |type|
+            next if type.name == :component
+            @types[type.name] = type
+        }
+    end
+
+    def list_types
+        puts "These are the types known to puppet:\n"
+        @types.keys.sort { |a, b|
+            a.to_s <=> b.to_s
+        }.each do |name|
+            type = @types[name]
+            s = type.doc.gsub(/\s+/, " ")
+            n = s.index(".")
+            if n.nil?
+                s = ".. no documentation .."
+            elsif n > 45
+                s = s[0, 45] + " ..."
+            else
+                s = s[0, n]
+            end
+            printf "%-15s - %s\n", name, s
+        end
+    end
+
+    def format_type(name, opts)
+        name = name.to_sym
+        unless @types.has_key?(name)
+            puts "Unknown type #{name}"
+            return
+        end
+        type = @types[name]
+        puts @format.header(name.to_s, "=")
+        puts @format.wrap(type.doc, :indent => 0, :scrub => true) + "\n\n"
+
+        puts @format.header("Parameters")
+        if opts[:parameters]
+            format_attrs(type, [:property, :param])
+        else
+            list_attrs(type, [:property, :param])
+        end
+        
+        if opts[:metaparams]
+            puts @format.header("Meta Parameters")
+            if opts[:parameters]
+                format_attrs(type, [:meta])
+            else
+                list_attrs(type, [:meta])
+            end
+        end
+
+        if type.providers.size > 0
+            puts @format.header("Providers")
+            if opts[:providers]
+                format_providers(type)
+            else
+                list_providers(type)
+            end                
+        end
+    end
+
+    # List details about attributes
+    def format_attrs(type, attrs)
+        docs = {}
+        type.eachattr do |obj, kind|
+            if attrs.include?(kind) && obj.name != :provider
+                docs[obj.name] = obj.doc
+            end
+        end
+
+        docs.sort { |a,b|
+            a[0].to_s <=> b[0].to_s
+        }.each { |name, doc|
+            print "\n- **%s**" % name
+            if type.namevar == name and name != :name
+                puts " (*namevar*)"
+            else
+                puts ""
+            end
+            puts @format.wrap(doc, :indent => 4, :scrub => true)
+        }
+    end
+
+    # List the names of attributes
+    def list_attrs(type, attrs)
+        params = []
+        type.eachattr do |obj, kind|
+            if attrs.include?(kind) && obj.name != :provider
+                params << obj.name.to_s
+            end
+        end
+        puts @format.wrap(params.sort.join(", "), :indent => 4)
+    end
+
+    def format_providers(type)
+        type.providers.sort { |a,b|
+            a.to_s <=> b.to_s
+        }.each { |prov|
+            puts "\n- **%s**" % prov
+            puts @format.wrap(type.provider(prov).doc, 
+                              :indent => 4, :scrub => true)
+        }
+    end
+
+    def list_providers(type)
+        list = type.providers.sort { |a,b|
+            a.to_s <=> b.to_s
+        }.join(", ")
+        puts @format.wrap(list, :indent => 4)
+    end
+    
+end
+
+def process_args
+    result = {
+        :list => false,
+        :providers => false,
+        :parameters => true,
+        :metaparams => false
+    }
+    opts = OptionParser.new("#{$0} [options] [type]")
+    opts.separator("  Print documentation for puppet types and their parameters")
+    opts.on("-l", "--list", "List all types") do |val|
+        result[:list] = true
+    end
+    opts.on("-p", "--providers", 
+            "Describe providers in detail") do |val|
+        result[:providers] = true
+    end
+    opts.on("-s", "--short", 
+            "Only list parameters without detail") do |val|
+        result[:parameters] = false
+    end
+    opts.on("-m", "--meta", 
+            "Include metaparams") do |val|
+        result[:metaparams] = true
+    end
+    result[:types] = opts.order(ARGV)
+    # Check for obviously bogus options
+    unless result[:list] || result[:types].size > 0
+        $stderr.puts opts
+        exit(1)
+    end
+    if result[:list] && result[:types].size > 0
+        $stderr.puts "Warning: ignoring types when listing all types"
+    end
+    
+    return result
+end
+
+opts = process_args
+
+doc = TypeDoc.new
+
+if opts[:list]
+    doc.list_types
+else
+    opts[:types].each { |name| doc.format_type(name, opts) }
+end
diff --git a/bin/puppet b/bin/puppet
index f3d8c25..bb73089 100755
--- a/bin/puppet
+++ b/bin/puppet
@@ -3,18 +3,18 @@
 #
 # = Synopsis
 #
-# Run a stand-alone +puppet+ manifest.
+# Run a stand-alone +puppet+ script.
 #
 # = Usage
 #
 #   puppet [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose]
-#               [--detailed-exitcodes] [-l|--logdest <file>] <file>
+#               [-l|--logdest <file>] <file>
 #
 # = Description
 #
-# This is the standalone puppet execution tool; use it to execute
-# individual manifests that you write.  If you need to execute site-wide
-# manifests, use +puppetd+ and +puppetmasterd+.
+# This is the standalone puppet execution script; use it to execute
+# individual scripts that you write.  If you need to execute site-wide
+# scripts, use +puppetd+ and +puppetmasterd+.
 #
 # = Options
 #
@@ -31,11 +31,6 @@
 # debug::
 #   Enable full debugging.
 #
-# detailed-exitcodes::
-#   Provide transaction information via exit codes.  If this is enabled, an exit
-#   code of '2' means there were changes, and an exit code of '4' means that there
-#   were failures during the transaction.
-#
 # help::
 #   Print this help message
 #
@@ -53,7 +48,7 @@
 #
 # = Example
 #
-#   puppet -l /tmp/manifest.log manifest.pp
+#   puppet -l /tmp/script.log script.pp
 #
 # = Author
 #
@@ -77,7 +72,6 @@ options = [
     [ "--loadclasses", "-L",		GetoptLong::NO_ARGUMENT ],
     [ "--verbose",  "-v",			GetoptLong::NO_ARGUMENT ],
     [ "--use-nodes",    			GetoptLong::NO_ARGUMENT ],
-    [ "--detailed-exitcodes",		GetoptLong::NO_ARGUMENT ],
     [ "--version",  "-V",           GetoptLong::NO_ARGUMENT ]
 ]
 
@@ -93,8 +87,7 @@ options = {
     :logfile => false,
     :loadclasses => false,
     :logset => false,
-    :code => nil,
-    :detailed_exits => false,
+    :code => nil
 }
 
 
@@ -125,8 +118,6 @@ begin
                 options[:code] = arg
             when "--loadclasses"
                 options[:loadclasses] = true
-            when "--detailed-exitcodes"
-                options[:detailed_exits] = true
             when "--logdest"
                 begin
                     Puppet::Util::Log.newdestination(arg)
@@ -150,9 +141,8 @@ if Puppet[:config] and File.exists? Puppet[:config]
     Puppet.settings.parse(Puppet[:config])
 end
 
-if Puppet.settings.print_configs?
-    exit(Puppet.settings.print_configs ? 0 : 1)
-end
+Puppet.genconfig
+Puppet.genmanifest
 
 # If noop is set, then also enable diffs
 if Puppet[:noop]
@@ -192,12 +182,11 @@ if Puppet[:parseonly]
 end
 
 # Collect our facts.
-facts = Puppet::Node::Facts.find(Puppet[:certname])
+facts = Puppet::Node::Facts.find("me")
+facts.name = facts.values["hostname"]
 
 # Find our Node
-unless node = Puppet::Node.find(Puppet[:certname])
-    raise "Could not find node %s" % Puppet[:certname]
-end
+node = Puppet::Node.find_by_any_name(facts.name)
 
 # Merge in the facts.
 node.merge(facts.values)
@@ -217,28 +206,15 @@ end
 
 begin
     # Compile our catalog
-    starttime = Time.now
-    catalog = Puppet::Node::Catalog.find(node.name, :use_node => node)
+    catalog = Puppet::Node::Catalog.find(node.name, :node => node)
 
     # Translate it to a RAL catalog
     catalog = catalog.to_ral
 
-    catalog.host_config = true if Puppet[:graph] or Puppet[:report]
-
     catalog.finalize
 
-    catalog.retrieval_duration = Time.now - starttime
-
     # And apply it
-    transaction = catalog.apply
-
-    status = 0
-    if not Puppet[:noop] and options[:detailed_exits] then
-        transaction.generate_report
-    	status |= 2 if transaction.report.metrics["changes"][:total] > 0
-        status |= 4 if transaction.report.metrics["resources"][:failed] > 0
-    end
-    exit(status)
+    catalog.apply
 rescue => detail
     if Puppet[:trace]
         puts detail.backtrace
diff --git a/bin/puppetca b/bin/puppetca
index 84c1599..3ad896b 100755
--- a/bin/puppetca
+++ b/bin/puppetca
@@ -32,16 +32,14 @@
 # '--genconfig'.
 #
 # all::
-#   Operate on all items.  Currently only makes sense with '--sign',
-#   '--clean', or '--list'.
+#   Operate on all outstanding requests.  Only makes sense with '--sign',
+#   or '--list'.
 #
 # clean::
 #    Remove all files related to a host from puppetca's storage. This is 
 #    useful when rebuilding hosts, since new certificate signing requests
 #    will only be honored if puppetca does not have a copy of a signed
 #    certificate for that host. The certificate of the host remains valid.
-#    If '--all' is specified then all host certificates, both signed and
-#    unsigned, will be removed.
 #
 # debug::
 #   Enable full debugging.
@@ -171,9 +169,8 @@ end
 # Now parse the config
 Puppet.parse_config
 
-if Puppet.settings.print_configs?
-    exit(Puppet.settings.print_configs ? 0 : 1)
-end
+Puppet.genconfig
+Puppet.genmanifest
 
 begin
     ca = Puppet::SSLCertificates::CA.new()
@@ -216,36 +213,20 @@ when :list
         puts ca.list_signed.collect { |cert | cert.sub(/^/,"+ ") }.join("\n")
     end
 when :clean
-    if hosts.empty? and all == false
-        $stderr.puts "You must specify one or more hosts to clean or --all to clean all host certificates"
+    if hosts.empty?
+        $stderr.puts "You must specify one or more hosts to clean"
         exit(24)
     end
-
     cleaned = false
-
-    if all
-        certs = ca.list
-        certs |= ca.list_signed
-            if certs.empty?
-                $stderr.puts "No certificates to clean"
-                exit(24)
-            end
-            certs.each do |c|
-                ca.clean(c)
-            end
-        cleaned = true
-    else
-        hosts.each do |host|
-            cert = ca.getclientcert(host)[0]
-                if cert.nil?
-                    $stderr.puts "Could not find client certificate for %s" % host
-                    next
-                end
-            ca.clean(host)
-            cleaned = true
+    hosts.each do |host|
+        cert = ca.getclientcert(host)[0]
+        if cert.nil?
+            $stderr.puts "Could not find client certificate for %s" % host
+            next
         end
+        ca.clean(host)
+        cleaned = true
     end
- 
     unless cleaned
         exit(27)
     end
@@ -253,7 +234,7 @@ when :sign
     to_sign = ARGV.collect { |h| h.downcase }
     unless to_sign.length > 0 or all
         $stderr.puts(
-            "You must specify one or more hosts to sign certificates for or --all to sign all certificates"
+            "You must specify to sign all certificates or you must specify hostnames"
         )
         exit(24)
     end
diff --git a/bin/puppetd b/bin/puppetd
index 0813745..f652e6b 100755
--- a/bin/puppetd
+++ b/bin/puppetd
@@ -10,7 +10,7 @@
 #
 #   puppetd  [-D|--daemonize|--no-daemonize] [-d|--debug] [--disable] [--enable]
 #       [-h|--help] [--fqdn <host name>] [-l|--logdest syslog|<file>|console]
-#       [-o|--onetime] [--serve <handler>] [-t|--test] [--noop]
+#       [-o|--onetime] [--serve <handler>] [-t|--test]
 #       [-V|--version] [-v|--verbose] [-w|--waitforcert <seconds>]
 #
 # = Description
@@ -57,7 +57,7 @@
 # parameter, so you can specify '--server <servername>' as an argument.
 #
 # See the configuration file documentation at
-# http://reductivelabs.com/trac/puppet/wiki/ConfigurationReference for
+# http://reductivelabs.com/projects/puppet/reference/configref.html for
 # the full list of acceptable parameters. A commented list of all
 # configuration options can also be generated by running puppetd with
 # '--genconfig'.
@@ -124,10 +124,6 @@
 #   Enable the most common options used for testing.  These are +onetime+,
 #   +verbose+, +ignorecache, and +no-usecacheonfailure+.
 #
-# noop::
-#   Use +noop+ mode where the daemon runs in a no-op or dry-run mode.  This is useful
-#   for seeing what changes Puppet will make without actually executing the changes.
-#
 # verbose::
 #   Turn on verbose reporting.
 #
@@ -162,7 +158,6 @@ trap(:INT) do
 end
 
 require 'puppet'
-require 'puppet/executables/client/certhandler'
 require 'puppet/network/client'
 require 'getoptlong'
 
@@ -299,9 +294,8 @@ unless options[:setdest]
     Puppet::Util::Log.newdestination(:syslog)
 end
 
-if Puppet.settings.print_configs?
-    exit(Puppet.settings.print_configs ? 0 : 1)
-end
+Puppet.genconfig
+Puppet.genmanifest
 
 # If noop is set, then also enable diffs
 if Puppet[:noop]
@@ -344,8 +338,36 @@ if Puppet[:daemonize]
     client.daemonize
 end
 
-unless Puppet::Executables::Client::CertHandler.new(options[:waitforcert], options[:onetime]).read_retrieve
-    client.recycle_connection
+unless Puppet::Network::HttpPool.read_cert
+    # If we don't already have the certificate, then create a client to
+    # request one.  Use the special ca stuff, don't use the normal server and port.
+    caclient = Puppet::Network::Client.ca.new()
+    if options[:waitforcert] > 0
+        begin
+            while ! caclient.request_cert do
+                Puppet.notice "Did not receive certificate"
+                sleep options[:waitforcert]
+            end
+        rescue => detail
+            Puppet.err "Could not request certificate: %s" % detail.to_s
+            exit(23)
+        end
+    else
+        unless caclient.request_cert
+            Puppet.notice "No certificates; exiting"
+            exit(1)
+        end
+    end
+
+    # Now read the new cert in.
+    if Puppet::Network::HttpPool.read_cert
+        # If we read it in, then get rid of our existing http connection.
+        client.recycle_connection
+        Puppet.notice "Got signed certificate"
+    else
+        Puppet.err "Could not read certificates after retrieving them"
+        exit(34)
+    end
 end
 
 objects = []
diff --git a/bin/puppetmasterd b/bin/puppetmasterd
index 03bd784..b4733e6 100755
--- a/bin/puppetmasterd
+++ b/bin/puppetmasterd
@@ -182,9 +182,8 @@ unless options[:setdest]
     Puppet::Util::Log.newdestination(:syslog)
 end
 
-if Puppet.settings.print_configs?
-    exit(Puppet.settings.print_configs ? 0 : 1)
-end
+Puppet.genconfig
+Puppet.genmanifest
 
 # A temporary solution, to at least make the master work for now.
 Puppet::Node::Facts.terminus_class = :yaml
diff --git a/bin/puppetrun b/bin/puppetrun
index 28f72d9..d0823b9 100755
--- a/bin/puppetrun
+++ b/bin/puppetrun
@@ -9,7 +9,7 @@
 #
 #   puppetrun [-a|--all] [-c|--class <class>] [-d|--debug] [-f|--foreground]
 #       [-h|--help] [--host <host>] [--no-fqdn] [--ignoreschedules]
-#       [-t|--tag <tag>] [--test] [-p|--ping]
+#       [-t|--tag <tag>] [--test]
 #
 # = Description
 #
@@ -108,10 +108,6 @@
 #   Print the hosts you would connect to but do not actually connect. This
 #   option requires LDAP support at this point.
 #
-# ping::
-#   
-#   Do a ICMP echo against the target host. Skip hosts that don't respond to ping.
-#
 # = Example
 #
 #   sudo puppetrun -p 10 --host host1 --host host2 -t remotefile -t webserver
@@ -143,12 +139,51 @@ begin
 rescue LoadError
     $stderr.puts "Failed to load ruby LDAP library. LDAP functionality will not be available"
 end
-
 require 'puppet'
 require 'puppet/network/client'
-require 'puppet/util/ldap/connection'
 require 'getoptlong'
 
+
+# Look up all nodes matching a given class in LDAP.
+def ldapnodes(klass, fqdn = true)
+    unless defined? @ldap
+        setupldap()
+    end
+
+    hosts = []
+
+    filter = nil
+    if klass == :all
+        filter = "objectclass=puppetclient"
+    else
+        filter = "puppetclass=#{klass}"
+    end
+    @ldap.search(Puppet[:ldapbase], 2, filter, "cn") do |entry|
+        # Skip the default host entry
+        if entry.dn =~ /cn=default,/
+            $stderr.puts "Skipping default host entry"
+            next
+        end
+
+        if fqdn
+            hosts << entry.dn.sub("cn=",'').sub(/ou=hosts,/i, '').gsub(",dc=",".")
+        else
+            hosts << entry.get_values("cn")[0]
+        end
+    end
+
+    return hosts
+end
+
+def setupldap
+    begin
+        @ldap = Puppet::Parser::Interpreter.ldap()
+    rescue => detail
+        $stderr.puts "Could not connect to LDAP: %s" % detail
+        exit(34)
+    end
+end
+
 flags = [
     [ "--all",      "-a",	        GetoptLong::NO_ARGUMENT ],
     [ "--tag",      "-t",           GetoptLong::REQUIRED_ARGUMENT ],
@@ -158,7 +193,6 @@ flags = [
     [ "--help",		"-h",			GetoptLong::NO_ARGUMENT ],
     [ "--host",         			GetoptLong::REQUIRED_ARGUMENT ],
     [ "--parallel", "-p",			GetoptLong::REQUIRED_ARGUMENT ],
-    [ "--ping", "-P",			GetoptLong::NO_ARGUMENT ],
     [ "--no-fqdn",  "-n",			GetoptLong::NO_ARGUMENT ],
     [ "--test",                     GetoptLong::NO_ARGUMENT ],
     [ "--version",  "-V",           GetoptLong::NO_ARGUMENT ]
@@ -173,7 +207,6 @@ options = {
     :ignoreschedules => false,
     :foreground => false,
     :parallel => 1,
-    :ping => false,
     :debug => false,
     :test => false,
     :all => false,
@@ -221,8 +254,6 @@ begin
                     $stderr.puts "Could not convert %s to an integer" % arg.inspect
                     exit(23)
                 end
-            when "--ping"
-                 options[:ping] = true 
             when "--foreground"
                 options[:foreground] = true
             when "--debug"
@@ -245,14 +276,13 @@ end
 # Now parse the config
 Puppet.parse_config
 
-if Puppet[:node_terminus] == "ldap" and (options[:all] or classes)
+if Puppet[:node_terminus] = "ldap"
     if options[:all]
-        hosts = Puppet::Node.search("whatever").collect { |node| node.name }
+        hosts = ldapnodes(:all, options[:fqdn])
         puts "all: %s" % hosts.join(", ")
     else
-        hosts = []
         classes.each do |klass|
-            list = Puppet::Node.search("whatever", :class => klass).collect { |node| node.name }
+            list = ldapnodes(klass, options[:fqdn])
             puts "%s: %s" % [klass, list.join(", ")]
 
             hosts += list
@@ -302,12 +332,12 @@ while go
     if children.length < options[:parallel] and ! todo.empty?
         host = todo.shift
         pid = fork do
-            if options[:ping]
-              out = %x{ping -c 1 #{host}}
-              unless $? == 0
-                  $stderr.print "Could not contact %s\n" % host
-                  next
-              end
+            # First make sure the client is up
+            out = %x{ping -c 1 #{host}}
+
+            unless $? == 0
+                $stderr.print "Could not contact %s\n" % host
+                next
             end
             client = Puppet::Network::Client.runner.new(
                 :Server => host,
diff --git a/bin/ralsh b/bin/ralsh
index 3cbfcad..1d00367 100755
--- a/bin/ralsh
+++ b/bin/ralsh
@@ -65,7 +65,7 @@
 #
 # This example uses ``ralsh`` to return Puppet configuration for the user ``luke``::
 #   
-#    $ ralsh user luke
+# $ ralsh user luke
 #    user { 'luke':
 #      home => '/home/luke',
 #      uid => '100',
diff --git a/conf/gentoo/init.d/puppet b/conf/gentoo/init.d/puppet
index 83d30b0..2fcd169 100644
--- a/conf/gentoo/init.d/puppet
+++ b/conf/gentoo/init.d/puppet
@@ -24,7 +24,7 @@ start() {
         [[ -n "${PUPPET_EXTRA_OPTS}" ]] && options="${options} ${PUPPET_EXTRA_OPTS}"
 
         ebegin "Starting puppet"
-        start-stop-daemon --start --quiet --exec /usr/bin/ruby /usr/bin/puppetd -- ${options}
+        start-stop-daemon --start --quiet --exec /usr/bin/puppetd -- ${options}
         eend $? "Failed to start puppet"
 }
 
diff --git a/conf/gentoo/init.d/puppetmaster b/conf/gentoo/init.d/puppetmaster
index 438ac21..67ada5c 100755
--- a/conf/gentoo/init.d/puppetmaster
+++ b/conf/gentoo/init.d/puppetmaster
@@ -1,51 +1,50 @@
 #!/sbin/runscript
-# Copyright 1999-2008 Gentoo Foundation
+# Copyright 1999-2004 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
+# $Header$
 
 depend() {
-	need net
-	before puppet
-	use dns logger
+        need net
+        use dns logger
 }
 
 checkconfig() {
-	if [[ ! -d "${PUPPETMASTER_PID_DIR}" ]] ; then
-		eerror "Please make sure PUPPETMASTER_PID_DIR is defined and points to a existing directory"
-		return 1
-	fi
+        if [[ ! -d "${PUPPETMASTER_PID_DIR}" ]] ; then
+               eerror "Please make sure PUPPETMASTER_PID_DIR is defined and points to a existing directory"
+               return 1
+        fi
 
-	local site_manifest="/etc/puppet/manifests/site.pp"
-	[[ -n "${PUPPETMASTER_MANIFEST}" ]] && site_manifest="${PUPPETMASTER_MANIFEST}"
+        local site_manifest="/etc/puppet/manifests/site.pp"
+        [[ -n "${PUPPETMASTER_MANIFEST}" ]] && site_manifest="${PUPPETMASTER_MANIFEST}"
 
-	if [ ! -f "${site_manifest}" ] ; then
-		eerror "Please create ${site_manifest} before running puppet"
-		return 1
-	fi
+        if [ ! -f "${site_manifest}" ] ; then
+                eerror "Please create ${site_manifest} before running puppet"
+                return 1
+        fi
 
-	return 0
+        return 0
 }
 
 start() {
-	checkconfig || return $?
+        checkconfig || return $?
 
-	local options=""
-	[[ -n "${PUPPETMASTER_MANIFEST}" ]]   && options="${options} --manifest=${PUPPETMASTER_MANIFEST}"
-	[[ -n "${PUPPETMASTER_LOG}" ]]        && options="${options} --logdest=${PUPPETMASTER_LOG}"
-	[[ -n "${PUPPETMASTER_EXTRA_OPTS}" ]] && options="${options} ${PUPPETMASTER_EXTRA_OPTS}"
+        local options=""
+        [[ -n "${PUPPETMASTER_MANIFEST}" ]]   && options="${options} --manifest=${PUPPETMASTER_MANIFEST}"
+        [[ -n "${PUPPETMASTER_LOG}" ]]        && options="${options} --logdest=${PUPPETMASTER_LOG}"
+        [[ -n "${PUPPETMASTER_EXTRA_OPTS}" ]] && options="${options} ${PUPPETMASTER_EXTRA_OPTS}"
 
-	ebegin "Starting puppetmaster"
-	start-stop-daemon --start --quiet --exec /usr/bin/ruby /usr/bin/puppetmasterd \
-		-- ${options}
-	eend $? "Failed to start puppetmaster"
+        ebegin "Starting puppetmaster"
+        start-stop-daemon --start --quiet --exec /usr/bin/puppetmasterd \
+                -- ${options}
+        eend $? "Failed to start puppetmaster"
 }
 
 stop() {
-	ebegin "Stopping puppetmaster"
-	start-stop-daemon --stop --quiet \
-		--pidfile ${PUPPETMASTER_PID_DIR}/puppetmasterd.pid
-	local ret=$?
-	eend ${ret} "Failed to stop puppetmaster"
-	rm -f ${PUPPETMASTER_PID_DIR}/puppetmasterd.pid
-	return ${ret}
+        ebegin "Stopping puppetmaster"
+        start-stop-daemon --stop --quiet \
+                --pidfile ${PUPPETMASTER_PID_DIR}/puppetmasterd.pid
+        local ret=$?
+        eend ${ret} "Failed to stop puppetmaster"
+        rm -f ${PUPPETMASTER_PID_DIR}/puppetmasterd.pid
+        return ${ret}
 }
-
diff --git a/conf/osx/PackageInfo.plist b/conf/osx/PackageInfo.plist
deleted file mode 100644
index 9706a80..0000000
--- a/conf/osx/PackageInfo.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleIdentifier</key>
-	<string>com.reductivelabs.puppet</string>
-	<key>CFBundleShortVersionString</key>
-	<string>{SHORTVERSION}</string>
-	<key>IFMajorVersion</key>
-	<integer>{MAJORVERSION}</integer>
-	<key>IFMinorVersion</key>
-	<integer>{MINORVERSION}</integer>
-	<key>IFPkgFlagAllowBackRev</key>
-	<false/>
-	<key>IFPkgFlagAuthorizationAction</key>
-	<string>RootAuthorization</string>
-	<key>IFPkgFlagDefaultLocation</key>
-	<string>/</string>
-	<key>IFPkgFlagFollowLinks</key>
-	<true/>
-	<key>IFPkgFlagInstallFat</key>
-	<false/>
-	<key>IFPkgFlagIsRequired</key>
-	<false/>
-	<key>IFPkgFlagOverwritePermissions</key>
-	<false/>
-	<key>IFPkgFlagRelocatable</key>
-	<false/>
-	<key>IFPkgFlagRestartAction</key>
-	<string>None</string>
-	<key>IFPkgFlagRootVolumeOnly</key>
-	<true/>
-	<key>IFPkgFlagUpdateInstalledLanguages</key>
-	<false/>
-</dict>
-</plist>
diff --git a/conf/osx/createpackage.sh b/conf/osx/createpackage.sh
deleted file mode 100755
index 32cbebf..0000000
--- a/conf/osx/createpackage.sh
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/bin/bash
-#
-# Script to build an "old style" not flat pkg out of the puppet repository.
-#
-# Author: Nigel Kersten (nigelk at google.com)
-#
-# Last Updated: 2008-07-31
-#
-# Copyright 2008 Google Inc.
-# 
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-#      http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License
-
-
-INSTALLRB="install.rb"
-BINDIR="/usr/bin"
-SITELIBDIR="/usr/lib/ruby/site_ruby/1.8"
-PACKAGEMAKER="/Developer/usr/bin/packagemaker"
-PROTO_PLIST="PackageInfo.plist"
-PREFLIGHT="preflight"
-
-
-function find_installer() {
-  # we walk up three directories to make this executable from the root, 
-  # root/conf or root/conf/osx
-  if [ -f "./${INSTALLRB}" ]; then
-    installer="$(pwd)/${INSTALLRB}"
-  elif [ -f "../${INSTALLRB}" ]; then
-    installer="$(pwd)/../${INSTALLRB}"
-  elif [ -f "../../${INSTALLRB}" ]; then
-    installer="$(pwd)/../${INSTALLRB}"
-  else
-    installer=""
-  fi
-}
-
-function find_puppet_root() {
-  puppet_root=$(dirname "${installer}")
-}
-
-function install_puppet() {
-  echo "Installing Puppet to ${pkgroot}"
-  "${installer}" --destdir="${pkgroot}" --bindir="${BINDIR}" --sitelibdir="${SITELIBDIR}"
-  chown -R root:admin "${pkgroot}"
-}
-
-function get_puppet_version() {
-  puppet_version=$(RUBYLIB="${pkgroot}/${SITELIBDIR}:${RUBYLIB}" ruby -e "require 'puppet'; puts Puppet.version")
-}
-
-function prepare_package() {
-  # As we can't specify to follow symlinks from the command line, we have
-  # to go through the hassle of creating an Info.plist file for packagemaker
-  # to look at for package creation and substitue the version strings out.
-  # Major/Minor versions can only be integers, so we have "0" and "245" for
-  # puppet version 0.24.5
-  # Note too that for 10.5 compatibility this Info.plist *must* be set to 
-  # follow symlinks.
-  VER1=$(echo ${puppet_version} | awk -F "." '{print $1}')
-  VER2=$(echo ${puppet_version} | awk -F "." '{print $2}')
-  VER3=$(echo ${puppet_version} | awk -F "." '{print $3}')
-  major_version="${VER1}"
-  minor_version="${VER2}${VER3}"
-  cp "${puppet_root}/conf/osx/${PROTO_PLIST}" "${pkgtemp}"
-  sed -i '' "s/{SHORTVERSION}/${puppet_version}/g" "${pkgtemp}/${PROTO_PLIST}"
-  sed -i '' "s/{MAJORVERSION}/${major_version}/g" "${pkgtemp}/${PROTO_PLIST}"
-  sed -i '' "s/{MINORVERSION}/${minor_version}/g" "${pkgtemp}/${PROTO_PLIST}"
-  
-  # We need to create a preflight script to remove traces of previous
-  # puppet installs due to limitations in Apple's pkg format.
-  mkdir "${pkgtemp}/scripts"
-  cp "${puppet_root}/conf/osx/${PREFLIGHT}" "${pkgtemp}/scripts"
-  
-  # substitute in the sitelibdir specified above on the assumption that this
-  # is where any previous puppet install exists that should be cleaned out.
-  sed -i '' "s|{SITELIBDIR}|${SITELIBDIR}|g" "${pkgtemp}/scripts/${PREFLIGHT}"
-  chmod 0755 "${pkgtemp}/scripts/${PREFLIGHT}"
-}
-
-function create_package() {
-  rm -fr "$(pwd)/puppet-${puppet_version}.pkg"
-  echo "Building package"
-  echo "Note that packagemaker is reknowned for spurious errors. Don't panic."
-  "${PACKAGEMAKER}" --root "${pkgroot}" \
-                    --info "${pkgtemp}/${PROTO_PLIST}" \
-                    --scripts ${pkgtemp}/scripts \
-                    --out "$(pwd)/puppet-${puppet_version}.pkg"
-  if [ $? -ne 0 ]; then
-    echo "There was a problem building the package."
-    cleanup_and_exit 1
-    exit 1
-  else
-    echo "The package has been built at:"
-    echo "$(pwd)/puppet-${puppet_version}.pkg"
-  fi
-}
-
-function cleanup_and_exit() {
-  if [ -d "${pkgroot}" ]; then
-    rm -fr "${pkgroot}"
-  fi
-  if [ -d "${pkgtemp}" ]; then
-    rm -fr "${pkgtemp}"
-  fi
-  exit $1
-}
-
-# Program entry point
-function main() {
-
-  if [ $(whoami) != "root" ]; then
-    echo "This script needs to be run as root via su or sudo."
-    cleanup_and_exit 1
-  fi
-
-  find_installer
-  
-  if [ ! "${installer}" ]; then
-    echo "Unable to find ${INSTALLRB}"
-    cleanup_and_exit 1
-  fi
-
-  find_puppet_root
-  
-  if [ ! "${puppet_root}" ]; then
-    echo "Unable to find puppet repository root."
-    cleanup_and_exit 1
-  fi
-  
-  pkgroot=$(mktemp -d -t puppetpkg)
-  
-  if [ ! "${pkgroot}" ]; then
-    echo "Unable to create temporary package root."
-    cleanup_and_exit 1
-  fi
-  
-  pkgtemp=$(mktemp -d -t puppettmp)
-  
-  if [ ! "${pkgtemp}" ]; then
-    echo "Unable to create temporary package root."
-    cleanup_and_exit 1
-  fi
-  
-  install_puppet
-  get_puppet_version
-  
-  if [ ! "${puppet_version}" ]; then
-    echo "Unable to retrieve puppet version"
-    cleanup_and_exit 1
-  fi
-  
-  prepare_package
-  create_package
-  
-  cleanup_and_exit 0
-}
-
-main "$@"
diff --git a/conf/osx/preflight b/conf/osx/preflight
deleted file mode 100755
index cde682b..0000000
--- a/conf/osx/preflight
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-#
-# Make sure that old puppet cruft is removed
-# This also allows us to downgrade puppet as
-# it's more likely that installing old versions
-# over new will cause issues.
-#
-# ${3} is the destination volume so that this works correctly
-# when being installed to volumes other than the current OS.
-
-/bin/rm -Rf "${3}{SITELIBDIR}/puppet"
-/bin/rm -Rf "${3}{SITELIBDIR}/puppet.rb"
diff --git a/conf/redhat/client.init b/conf/redhat/client.init
index 44caab1..b77bd01 100644
--- a/conf/redhat/client.init
+++ b/conf/redhat/client.init
@@ -62,11 +62,6 @@ restart() {
     start
 }
 
-genconfig() {
-  echo -n $"Generate configuration puppet: "
-  $puppetd ${PUPPET_OPTS} ${PUPPET_EXTRA_OPTS} --genconfig
-}
-
 case "$1" in
   start)
 	start
@@ -84,18 +79,15 @@ case "$1" in
 	[ -f "$pidfile" ] && restart
 	;;
   status)
-        status -p "$pidfile" $puppetd
+        status $puppetd
         RETVAL=$?
 	;;
   once)
         shift
         $puppetd -o ${PUPPET_OPTS} ${PUPPET_EXTRA_OPTS} $@
         ;;
-  genconfig)
-	genconfig
-	;;
   *)
-	echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|once|genconfig}"
+	echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|once}"
 	exit 1
 esac
 
diff --git a/conf/redhat/puppet.spec b/conf/redhat/puppet.spec
index d71b862..65cb493 100644
--- a/conf/redhat/puppet.spec
+++ b/conf/redhat/puppet.spec
@@ -2,12 +2,12 @@
 %define pbuild %{_builddir}/%{name}-%{version}
 %define confdir conf/redhat
 
-%define has_ruby_abi 0%{?fedora:%fedora} >= 5 || 0%{?rhel:%rhel} >= 5 || 0%{?centos:%centos} >= 5
+%define has_ruby_abi 0%{?fedora:%fedora} >= 5 || 0%{?rhel:%rhel} >= 5
 %define has_ruby_noarch %has_ruby_abi
 
 Summary: A network tool for managing many disparate systems
 Name: puppet
-Version: 0.24.6
+Version: 0.24.4
 Release: 1%{?dist}
 License: GPLv2+
 Group: System Environment/Base
@@ -51,8 +51,8 @@ done
 # Fix some rpmlint complaints
 for f in mac_dscl.pp mac_dscl_revert.pp \
          mac_netinfo.pp mac_pkgdmg.pp ; do
-  sed -i -e'1d' examples/$f
-  chmod a-x examples/$f
+  sed -i -e'1d' examples/code/$f
+  chmod a-x examples/code/$f
 done
 
 find examples/ -type f -empty | xargs rm
@@ -65,7 +65,6 @@ install -d -m0755 %{buildroot}%{_bindir}
 install -d -m0755 %{buildroot}%{ruby_sitelibdir}
 install -d -m0755 %{buildroot}%{_sysconfdir}/puppet/manifests
 install -d -m0755 %{buildroot}%{_docdir}/%{name}-%{version}
-install -d -m0755 %{buildroot}%{_mandir}/man8
 install -d -m0755 %{buildroot}%{_localstatedir}/lib/puppet
 install -d -m0755 %{buildroot}%{_localstatedir}/run/puppet
 install -d -m0755 %{buildroot}%{_localstatedir}/log/puppet
@@ -74,7 +73,6 @@ mv %{buildroot}%{_sbindir}/puppet %{buildroot}%{_bindir}/puppet
 mv %{buildroot}%{_sbindir}/ralsh %{buildroot}%{_bindir}/ralsh
 mv %{buildroot}%{_sbindir}/filebucket %{buildroot}%{_bindir}/filebucket
 mv %{buildroot}%{_sbindir}/puppetrun %{buildroot}%{_bindir}/puppetrun
-mv %{buildroot}%{_sbindir}/puppetdoc %{buildroot}%{_bindir}/puppetdoc
 install -Dp -m0644 %{pbuild}/lib/puppet.rb %{buildroot}%{ruby_sitelibdir}/puppet.rb
 cp -a %{pbuild}/lib/puppet %{buildroot}%{ruby_sitelibdir}
 find %{buildroot}%{ruby_sitelibdir} -type f -perm +ugo+x -print0 | xargs -0 -r chmod a-x
@@ -85,7 +83,6 @@ install -Dp -m0755 %{confdir}/server.init %{buildroot}%{_initrddir}/puppetmaster
 install -Dp -m0644 %{confdir}/fileserver.conf %{buildroot}%{_sysconfdir}/puppet/fileserver.conf
 install -Dp -m0644 %{confdir}/puppet.conf %{buildroot}%{_sysconfdir}/puppet/puppet.conf
 install -Dp -m0644 %{confdir}/logrotate %{buildroot}%{_sysconfdir}/logrotate.d/puppet
-install -Dp -m0644 man/man8/* %{buildroot}%{_mandir}/man8
 # We need something for these ghosted files, otherwise rpmbuild
 # will complain loudly. They won't be included in the binary packages
 touch %{buildroot}%{_sysconfdir}/puppet/puppetmasterd.conf
@@ -97,8 +94,6 @@ touch %{buildroot}%{_sysconfdir}/puppet/puppetd.conf
 %{_bindir}/puppet
 %{_bindir}/ralsh
 %{_bindir}/filebucket
-%{_bindir}/puppetdoc
-%exclude %{_mandir}/man8/pi.8.gz
 %{_sbindir}/puppetd
 %{ruby_sitelibdir}/*
 %{_initrddir}/puppet
@@ -107,17 +102,13 @@ touch %{buildroot}%{_sysconfdir}/puppet/puppetd.conf
 %config(noreplace) %{_sysconfdir}/puppet/puppet.conf
 %ghost %config(noreplace,missingok) %{_sysconfdir}/puppet/puppetd.conf
 %doc CHANGELOG COPYING LICENSE README examples
+%exclude %{_sbindir}/puppetdoc
 %config(noreplace) %{_sysconfdir}/logrotate.d/puppet
 # These need to be owned by puppet so the server can
 # write to them
 %attr(-, puppet, puppet) %{_localstatedir}/run/puppet
 %attr(-, puppet, puppet) %{_localstatedir}/log/puppet
 %attr(-, puppet, puppet) %{_localstatedir}/lib/puppet
-%doc %{_mandir}/man8/puppet.8.gz
-%doc %{_mandir}/man8/puppet.conf.8.gz
-%doc %{_mandir}/man8/puppetd.8.gz
-%doc %{_mandir}/man8/ralsh.8.gz
-%doc %{_mandir}/man8/puppetdoc.8.gz
 
 %files server
 %defattr(-, root, root, 0755)
@@ -130,10 +121,6 @@ touch %{buildroot}%{_sysconfdir}/puppet/puppetd.conf
 %ghost %config(noreplace,missingok) %{_sysconfdir}/puppet/puppetca.conf
 %ghost %config(noreplace,missingok) %{_sysconfdir}/puppet/puppetmasterd.conf
 %{_sbindir}/puppetca
-%doc %{_mandir}/man8/filebucket.8.gz
-%doc %{_mandir}/man8/puppetca.8.gz
-%doc %{_mandir}/man8/puppetmasterd.8.gz
-%doc %{_mandir}/man8/puppetrun.8.gz
 
 %pre
 /usr/sbin/groupadd -r puppet 2>/dev/null || :
@@ -170,24 +157,6 @@ fi
 rm -rf %{buildroot}
 
 %changelog
-* Mon Jul 28 2008 David Lutterkort <dlutter at redhat.com> - 0.24.5-1
-- Add /usr/bin/puppetdoc
-
-* Thu Jul 24 2008 Brenton Leanhardt <bleanhar at redhat.com>
-- New version
-- man pages now ship with tarball
-- examples/code moved to root examples dir in upstream tarball
-
-* Tue Mar 25 2008 David Lutterkort <dlutter at redhat.com> - 0.24.4-1
-- Add man pages (from separate tarball, upstream will fix to
-  include in main tarball)
-
-* Mon Mar 24 2008 David Lutterkort <dlutter at redhat.com> - 0.24.3-1
-- New version
-
-* Wed Mar  5 2008 David Lutterkort <dlutter at redhat.com> - 0.24.2-1
-- New version
-
 * Sat Dec 22 2007 David Lutterkort <dlutter at redhat.com> - 0.24.1-1
 - New version
 
diff --git a/conf/redhat/server.init b/conf/redhat/server.init
index 6871b9a..b646221 100644
--- a/conf/redhat/server.init
+++ b/conf/redhat/server.init
@@ -1,8 +1,7 @@
 #!/bin/bash
 # puppetmaster  This shell script enables the puppetmaster server.
 #
-# Authors:       Duane Griffin <d.griffin at psenterprise.com>
-#                Peter Meier <peter.meier at immerda.ch> (Mongrel enhancements)
+# Author:       Duane Griffin <d.griffin at psenterprise.com>
 #
 # chkconfig: - 65 45
 #
@@ -23,11 +22,6 @@ fi
 
 PUPPETMASTER_OPTS=""
 [ -n "$PUPPETMASTER_MANIFEST" ] && PUPPETMASTER_OPTS="--manifest=${PUPPETMASTER_MANIFEST}"
-if [ -n "$PUPPETMASTER_PORTS" ] && [ ${#PUPPETMASTER_PORTS[@]} -gt 1 ]; then
-    PUPPETMASTER_OPTS="$PUPPETMASTER_OPTS --servertype=mongrel"
-elif [ -n "$PUPPETMASTER_PORTS" ] && [ ${#PUPPETMASTER_PORTS[@]} -eq 1 ]; then
-    PUPPETMASTER_OPTS="${PUPPETMASTER_OPTS} --masterport=${PUPPETMASTER_PORTS[0]}" 
-fi
 [ -n "$PUPPETMASTER_LOG" ] && PUPPETMASTER_OPTS="${PUPPETMASTER_OPTS} --logdest=${PUPPETMASTER_LOG}"
 PUPPETMASTER_OPTS="${PUPPETMASTER_OPTS} \
 	${PUPPETMASTER_EXTRA_OPTS}"
@@ -42,16 +36,8 @@ start() {
 
 	# Confirm the manifest exists
 	if [ -r $PUPPETMASTER_MANIFEST ]; then
-        if [ -n "$PUPPETMASTER_PORTS" ] && [ ${#PUPPETMASTER_PORTS[@]} -gt 1 ]; then
-            for ((i=0; i<${#PUPPETMASTER_PORTS[@]}; i++)); do
-                echo -en "\nPort: ${PUPPETMASTER_PORTS[$i]}"
-                daemon $PUPPETMASTER $PUPPETMASTER_OPTS --masterport=${PUPPETMASTER_PORTS[$i]} --pidfile=/var/run/puppet/puppetmaster.${PUPPETMASTER_PORTS[$i]}.pid
-                ret=$?; [ $ret != 0 ] && RETVAL=$ret
-            done
-        else
-            daemon $PUPPETMASTER $PUPPETMASTER_OPTS
-            RETVAL=$?
-        fi
+		daemon $PUPPETMASTER $PUPPETMASTER_OPTS
+		RETVAL=$?
 	else
 		failure $"Manifest does not exist: $PUPPETMASTER_MANIFEST"
 		echo
@@ -64,16 +50,8 @@ start() {
 
 stop() {
 	echo -n  $"Stopping puppetmaster: "
-    if [ -n "$PUPPETMASTER_PORTS" ] && [ ${#PUPPETMASTER_PORTS[@]} -gt 1 ]; then
-        for ((i=0; i<${#PUPPETMASTER_PORTS[@]}; i++)); do
-            echo -en "\nPort: ${PUPPETMASTER_PORTS[$i]}"
-            killproc -p /var/run/puppet/puppetmaster.${PUPPETMASTER_PORTS[$i]}.pid puppetmaster 
-            ret=$?; [ $ret != 0 ] && RETVAL=$ret
-        done
-    else
-       killproc $PUPPETMASTER
-       RETVAL=$?
-    fi
+	killproc $PUPPETMASTER
+	RETVAL=$?
 	echo
 	[ $RETVAL -eq 0 ] && rm -f "$lockfile"
 	return $RETVAL
@@ -84,25 +62,6 @@ restart() {
   start
 }
 
-genconfig() {
-  echo -n $"Generate configuration puppetmaster: "
-  $PUPPETMASTER $PUPPETMASTER_OPTS --genconfig
-}
-
-puppetmaster_status() {
-    if [ -n "$PUPPETMASTER_PORTS" ] && [ ${#PUPPETMASTER_PORTS[@]} -gt 1 ]; then
-        for ((i=0; i<${#PUPPETMASTER_PORTS[@]}; i++)); do
-            echo -en "Port ${PUPPETMASTER_PORTS[$i]}: "
-            status -p /var/run/puppet/puppetmaster.${PUPPETMASTER_PORTS[$i]}.pid puppetmaster 
-            ret=$?; [ $ret != 0 ] && RETVAL=$ret
-        done 
-    else
-	    status $PUPPETMASTER
-        RETVAL=$?
-    fi
-    return $RETVAL
-}
-
 case "$1" in
   start)
 	start
@@ -117,13 +76,11 @@ case "$1" in
 	[ -f "$lockfile" ] && restart
 	;;
   status)
-    puppetmaster_status
-	;;
-  genconfig)
-	genconfig
+	status $PUPPETMASTER
+        RETVAL=$?
 	;;
   *)
-	echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|genconfig}"
+	echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}"
 	exit 1
 esac
 
diff --git a/conf/redhat/server.sysconfig b/conf/redhat/server.sysconfig
index befb40f..fe673cc 100644
--- a/conf/redhat/server.sysconfig
+++ b/conf/redhat/server.sysconfig
@@ -5,27 +5,5 @@
 # Specify syslog to send log messages to the system log.
 #PUPPETMASTER_LOG=syslog
 
-# You may specify an alternate port or an array of ports on which 
-# puppetmaster should listen. Default is: 8140
-# If you specify more than one port, the puppetmaster ist automatically
-# started with the servertype set to mongrel. This might be interesting
-# if you'd like to run your puppetmaster in a loadbalanced cluster.
-# Please note: this won't setup nor start any loadbalancer. 
-# If you'd like to run puppetmaster with mongrel as servertype but only
-# on one (specified) port, you have to add --servertype=mongrel to
-# PUPPETMASTER_EXTRA_OPTS.
-# Default: Empty (Puppetmaster isn't started with mongrel, nor on a 
-# specific port)
-#
-# Please note: Due to reduced options in the rc-functions lib in RHEL/Centos
-# versions prior to 5, this feature won't work. Fedora versions >= 8 are 
-# known to work.
-#PUPPETMASTER_PORTS=""
-# Puppetmaster on a different port, run with standard webrick servertype
-#PUPPETMASTER_PORTS="8141"
-# Example with multiple ports which will start puppetmaster with mongrel
-# as a servertype
-#PUPPETMASTER_PORTS=( 18140 18141 18142 18143 )
-
 # You may specify other parameters to the puppetmaster here
 #PUPPETMASTER_EXTRA_OPTS=--noca
diff --git a/conf/debian/README.source b/debian/README.source
similarity index 100%
rename from conf/debian/README.source
rename to debian/README.source
diff --git a/conf/debian/TODO.Debian b/debian/TODO.Debian
similarity index 100%
rename from conf/debian/TODO.Debian
rename to debian/TODO.Debian
diff --git a/conf/debian/changelog b/debian/changelog
similarity index 100%
rename from conf/debian/changelog
rename to debian/changelog
diff --git a/conf/debian/compat b/debian/compat
similarity index 100%
rename from conf/debian/compat
rename to debian/compat
diff --git a/conf/debian/control b/debian/control
similarity index 100%
rename from conf/debian/control
rename to debian/control
diff --git a/conf/debian/copyright b/debian/copyright
similarity index 100%
rename from conf/debian/copyright
rename to debian/copyright
diff --git a/conf/debian/docs b/debian/docs
similarity index 100%
rename from conf/debian/docs
rename to debian/docs
diff --git a/conf/debian/fileserver.conf b/debian/fileserver.conf
similarity index 100%
rename from conf/debian/fileserver.conf
rename to debian/fileserver.conf
diff --git a/conf/debian/puppet.NEWS b/debian/puppet.NEWS
similarity index 100%
rename from conf/debian/puppet.NEWS
rename to debian/puppet.NEWS
diff --git a/conf/debian/puppet.conf b/debian/puppet.conf
similarity index 100%
rename from conf/debian/puppet.conf
rename to debian/puppet.conf
diff --git a/conf/debian/puppet.dirs b/debian/puppet.dirs
similarity index 100%
rename from conf/debian/puppet.dirs
rename to debian/puppet.dirs
diff --git a/conf/debian/puppet.files b/debian/puppet.files
similarity index 100%
rename from conf/debian/puppet.files
rename to debian/puppet.files
diff --git a/conf/debian/puppet.init b/debian/puppet.init
similarity index 100%
rename from conf/debian/puppet.init
rename to debian/puppet.init
diff --git a/conf/debian/puppet.logrotate b/debian/puppet.logrotate
similarity index 100%
rename from conf/debian/puppet.logrotate
rename to debian/puppet.logrotate
diff --git a/conf/debian/puppet.postinst b/debian/puppet.postinst
similarity index 100%
rename from conf/debian/puppet.postinst
rename to debian/puppet.postinst
diff --git a/conf/debian/puppet.postrm b/debian/puppet.postrm
similarity index 100%
rename from conf/debian/puppet.postrm
rename to debian/puppet.postrm
diff --git a/conf/debian/puppet.preinst b/debian/puppet.preinst
similarity index 100%
rename from conf/debian/puppet.preinst
rename to debian/puppet.preinst
diff --git a/conf/debian/puppetmaster.files b/debian/puppetmaster.files
similarity index 100%
rename from conf/debian/puppetmaster.files
rename to debian/puppetmaster.files
diff --git a/conf/debian/puppetmaster.init b/debian/puppetmaster.init
similarity index 100%
rename from conf/debian/puppetmaster.init
rename to debian/puppetmaster.init
diff --git a/conf/debian/rules b/debian/rules
similarity index 100%
rename from conf/debian/rules
rename to debian/rules
diff --git a/conf/debian/watch b/debian/watch
similarity index 100%
rename from conf/debian/watch
rename to debian/watch
diff --git a/examples/allatonce b/examples/code/allatonce
similarity index 100%
rename from examples/allatonce
rename to examples/code/allatonce
diff --git a/examples/assignments b/examples/code/assignments
similarity index 100%
rename from examples/assignments
rename to examples/code/assignments
diff --git a/examples/components b/examples/code/components
similarity index 100%
rename from examples/components
rename to examples/code/components
diff --git a/examples/execs b/examples/code/execs
similarity index 100%
rename from examples/execs
rename to examples/code/execs
diff --git a/examples/file.bl b/examples/code/file.bl
similarity index 100%
rename from examples/file.bl
rename to examples/code/file.bl
diff --git a/examples/filedefaults b/examples/code/filedefaults
similarity index 100%
rename from examples/filedefaults
rename to examples/code/filedefaults
diff --git a/examples/fileparsing b/examples/code/fileparsing
similarity index 100%
rename from examples/fileparsing
rename to examples/code/fileparsing
diff --git a/examples/filerecursion b/examples/code/filerecursion
similarity index 100%
rename from examples/filerecursion
rename to examples/code/filerecursion
diff --git a/examples/functions b/examples/code/functions
similarity index 100%
rename from examples/functions
rename to examples/code/functions
diff --git a/examples/groups b/examples/code/groups
similarity index 100%
rename from examples/groups
rename to examples/code/groups
diff --git a/examples/head b/examples/code/head
similarity index 100%
rename from examples/head
rename to examples/code/head
diff --git a/examples/importing b/examples/code/importing
similarity index 100%
rename from examples/importing
rename to examples/code/importing
diff --git a/examples/mac_automount.pp b/examples/code/mac_automount.pp
similarity index 100%
rename from examples/mac_automount.pp
rename to examples/code/mac_automount.pp
diff --git a/examples/mac_dscl.pp b/examples/code/mac_dscl.pp
similarity index 100%
rename from examples/mac_dscl.pp
rename to examples/code/mac_dscl.pp
diff --git a/examples/mac_dscl_revert.pp b/examples/code/mac_dscl_revert.pp
similarity index 100%
rename from examples/mac_dscl_revert.pp
rename to examples/code/mac_dscl_revert.pp
diff --git a/examples/mac_netinfo.pp b/examples/code/mac_netinfo.pp
similarity index 100%
rename from examples/mac_netinfo.pp
rename to examples/code/mac_netinfo.pp
diff --git a/examples/mac_pkgdmg.pp b/examples/code/mac_pkgdmg.pp
similarity index 100%
rename from examples/mac_pkgdmg.pp
rename to examples/code/mac_pkgdmg.pp
diff --git a/examples/modules/sample-module.pp b/examples/code/modules/sample-module.pp
similarity index 100%
rename from examples/modules/sample-module.pp
rename to examples/code/modules/sample-module.pp
diff --git a/examples/modules/sample-module/README.txt b/examples/code/modules/sample-module/README.txt
similarity index 100%
rename from examples/modules/sample-module/README.txt
rename to examples/code/modules/sample-module/README.txt
diff --git a/examples/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb b/examples/code/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb
similarity index 100%
rename from examples/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb
rename to examples/code/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb
diff --git a/examples/modules/sample-module/manifests/init.pp b/examples/code/modules/sample-module/manifests/init.pp
similarity index 100%
rename from examples/modules/sample-module/manifests/init.pp
rename to examples/code/modules/sample-module/manifests/init.pp
diff --git a/examples/modules/sample-module/templates/sample.erb b/examples/code/modules/sample-module/templates/sample.erb
similarity index 100%
rename from examples/modules/sample-module/templates/sample.erb
rename to examples/code/modules/sample-module/templates/sample.erb
diff --git a/examples/nodes b/examples/code/nodes
similarity index 100%
rename from examples/nodes
rename to examples/code/nodes
diff --git a/examples/one b/examples/code/one
similarity index 100%
rename from examples/one
rename to examples/code/one
diff --git a/examples/relationships b/examples/code/relationships
similarity index 100%
rename from examples/relationships
rename to examples/code/relationships
diff --git a/examples/selectors b/examples/code/selectors
similarity index 100%
rename from examples/selectors
rename to examples/code/selectors
diff --git a/examples/simpletests b/examples/code/simpletests
similarity index 100%
rename from examples/simpletests
rename to examples/code/simpletests
diff --git a/examples/svncommit b/examples/code/svncommit
similarity index 100%
rename from examples/svncommit
rename to examples/code/svncommit
diff --git a/ext/bin/sleeper b/examples/root/bin/sleeper
similarity index 100%
rename from ext/bin/sleeper
rename to examples/root/bin/sleeper
diff --git a/examples/etc/otherfile b/examples/root/etc/configfile
similarity index 100%
copy from examples/etc/otherfile
copy to examples/root/etc/configfile
diff --git a/examples/root/etc/debian-passwd b/examples/root/etc/debian-passwd
new file mode 100644
index 0000000..59cdf4a
--- /dev/null
+++ b/examples/root/etc/debian-passwd
@@ -0,0 +1,29 @@
+root:x:0:0:root:/root:/bin/bash
+daemon:x:1:1:daemon:/usr/sbin:/bin/sh
+bin:x:2:2:bin:/bin:/bin/sh
+sys:x:3:3:sys:/dev:/bin/sh
+sync:x:4:65534:sync:/bin:/bin/sync
+games:x:5:60:games:/usr/games:/bin/sh
+man:x:6:12:man:/var/cache/man:/bin/sh
+lp:x:7:7:lp:/var/spool/lpd:/bin/sh
+mail:x:8:8:mail:/var/mail:/bin/sh
+news:x:9:9:news:/var/spool/news:/bin/sh
+uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
+proxy:x:13:13:proxy:/bin:/bin/sh
+postgres:x:31:32:postgres:/var/lib/postgres:/bin/sh
+www-data:x:33:33:www-data:/var/www:/bin/sh
+backup:x:34:34:backup:/var/backups:/bin/sh
+operator:x:37:37:Operator:/var:/bin/sh
+list:x:38:38:Mailing List Manager:/var/list:/bin/sh
+irc:x:39:39:ircd:/var/run/ircd:/bin/sh
+gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
+nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
+sshd:x:102:65534::/var/run/sshd:/bin/false
+gdm:x:101:101:Gnome Display Manager:/var/lib/gdm:/bin/false
+telnetd:x:103:103::/usr/lib/telnetd:/bin/false
+nagios:x:1000:1001::/home/nagios:
+messagebus:x:104:107::/var/run/dbus:/bin/false
+saned:x:109:109::/home/saned:/bin/false
+ganglia:x:105:110:Ganglia Monitor:/var/lib/ganglia:/bin/false
+zope:x:106:111::/var/lib/zope2.7/var:/bin/false
+fbgetty:x:112:112::/home/fbgetty:/bin/false
diff --git a/examples/root/etc/debian-syslog.conf b/examples/root/etc/debian-syslog.conf
new file mode 100644
index 0000000..8f29259
--- /dev/null
+++ b/examples/root/etc/debian-syslog.conf
@@ -0,0 +1,71 @@
+#  /etc/syslog.conf	Configuration file for syslogd.
+#
+#			For more information see syslog.conf(5)
+#			manpage.
+
+#
+# First some standard logfiles.  Log by facility.
+#
+
+auth,authpriv.*			/var/log/auth.log
+*.*;auth,authpriv.none		-/var/log/syslog
+#cron.*				/var/log/cron.log
+daemon.*			-/var/log/daemon.log
+kern.*				-/var/log/kern.log
+lpr.*				-/var/log/lpr.log
+mail.*				-/var/log/mail.log
+user.*				-/var/log/user.log
+uucp.*				/var/log/uucp.log
+
+#
+# Logging for the mail system.  Split it up so that
+# it is easy to write scripts to parse these files.
+#
+mail.info			-/var/log/mail.info
+mail.warn			-/var/log/mail.warn
+mail.err			/var/log/mail.err
+
+# Logging for INN news system
+#
+news.crit			/var/log/news/news.crit
+news.err			/var/log/news/news.err
+news.notice			-/var/log/news/news.notice
+
+#
+# Some `catch-all' logfiles.
+#
+*.=debug;\
+	auth,authpriv.none;\
+	news.none;mail.none	-/var/log/debug
+*.=info;*.=notice;*.=warn;\
+	auth,authpriv.none;\
+	cron,daemon.none;\
+	mail,news.none		-/var/log/messages
+
+#
+# Emergencies are sent to everybody logged in.
+#
+*.emerg				*
+
+#
+# I like to have messages displayed on the console, but only on a virtual
+# console I usually leave idle.
+#
+#daemon,mail.*;\
+#	news.=crit;news.=err;news.=notice;\
+#	*.=debug;*.=info;\
+#	*.=notice;*.=warn	/dev/tty8
+
+# The named pipe /dev/xconsole is for the `xconsole' utility.  To use it,
+# you must invoke `xconsole' with the `-file' option:
+# 
+#    $ xconsole -file /dev/xconsole [...]
+#
+# NOTE: adjust the list below, or you'll go crazy if you have a reasonably
+#      busy site..
+#
+daemon.*;mail.*;\
+	news.crit;news.err;news.notice;\
+	*.=debug;*.=info;\
+	*.=notice;*.=warn	|/dev/xconsole
+
diff --git a/examples/etc/init.d/sleeper b/examples/root/etc/init.d/sleeper
similarity index 100%
rename from examples/etc/init.d/sleeper
rename to examples/root/etc/init.d/sleeper
diff --git a/examples/etc/otherfile b/examples/root/etc/otherfile
similarity index 100%
copy from examples/etc/otherfile
copy to examples/root/etc/otherfile
diff --git a/examples/etc/puppet/fileserver.conf b/examples/root/etc/puppet/fileserver.conf
similarity index 100%
rename from examples/etc/puppet/fileserver.conf
rename to examples/root/etc/puppet/fileserver.conf
diff --git a/examples/etc/puppet/namespaceauth.conf b/examples/root/etc/puppet/namespaceauth.conf
similarity index 100%
rename from examples/etc/puppet/namespaceauth.conf
rename to examples/root/etc/puppet/namespaceauth.conf
diff --git a/examples/etc/puppet/puppet.conf b/examples/root/etc/puppet/puppet.conf
similarity index 100%
rename from examples/etc/puppet/puppet.conf
rename to examples/root/etc/puppet/puppet.conf
diff --git a/examples/etc/puppet/tagmail.conf b/examples/root/etc/puppet/tagmail.conf
similarity index 100%
rename from examples/etc/puppet/tagmail.conf
rename to examples/root/etc/puppet/tagmail.conf
diff --git a/ext/autotest/Rakefile b/ext/autotest/Rakefile
deleted file mode 100644
index 86327c0..0000000
--- a/ext/autotest/Rakefile
+++ /dev/null
@@ -1,8 +0,0 @@
-dest = File.expand_path("~/.autotest")
-file dest => ["config", "Rakefile"] do
-    sh "cp config #{dest}"
-end
-
-task :install => dest
-
-task :default => :install
diff --git a/ext/autotest/config b/ext/autotest/config
deleted file mode 100644
index d37c1b2..0000000
--- a/ext/autotest/config
+++ /dev/null
@@ -1,43 +0,0 @@
-# vim: syntax=ruby
-# From http://pastie.caboo.se/115692, linked from rickbradley
-
-require 'autotest/redgreen'
-require 'autotest/timestamp'
-
-Autotest.send(:alias_method, :real_find_files, :find_files)
-Autotest.send(:define_method, :find_files) do |*args| 
-  real_find_files.reject do |k, v|
-    if (ENV['AUTOTEST'] and !ENV['AUTOTEST'].empty?)
-      !Regexp.new(ENV['AUTOTEST']).match(k)
-    end
-  end
-end
-
-module Autotest::Growl
-
-  def self.growl title, msg, img, pri=0, sticky="" 
-    system "growlnotify -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}" 
-  end
-
-  Autotest.add_hook :ran_command do |at|
-    image_root = "~/.autotest_images" 
-    results = [at.results].flatten.join("\n")
-    output = results.slice(/(\d+)\stests,\s(\d+)\sassertions,\s(\d+)\sfailures,\s(\d+)\serrors/)
-    if output
-      if $~[3].to_i > 0 || $~[4].to_i > 0
-        growl "FAIL", "#{output}", "#{image_root}/fail.png", 2
-      else
-        growl "Pass", "#{output}", "#{image_root}/pass.png" 
-      end
-    end
-
-    output = results.slice(/(\d+)\sexamples,\s(\d+)\sfailures?(,\s+\d+\s+pending)?/)
-    if output
-      if $~[2].to_i > 0 || $~[4].to_i > 0
-        growl "FAIL", "#{output}", "#{image_root}/fail.png", 2
-      else
-        growl "Pass", "#{output}", "#{image_root}/pass.png" 
-      end
-    end
-  end
-end
diff --git a/ext/autotest/readme.rst b/ext/autotest/readme.rst
deleted file mode 100644
index 93d9ed2..0000000
--- a/ext/autotest/readme.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-Autotest is a simple tool that automatically links tests with the files being
-tested, and runs tests automatically when either the test or code has changed.
-
-If you are running on a Mac and have growlnotify_ installed, install the
-ZenTest_ gem, then copy the ``config`` file to ``~/.autotest`` (or just
-run ``rake`` in this directory).
-
-Once you have ``autotest`` installed, change to the root of your Puppet
-git repository and run ``autotest`` with no arguments.  To refresh the list
-of files to scan, hit ``^c`` (that is, control-c).
-
-It's recommended you leave this running in another terminal during all
-development, preferably on another monitor.
-
-.. _zentest: http://www.zenspider.com/ZSS/Products/ZenTest/
-.. _growlnotify: http://growl.info/extras.php
diff --git a/ext/emacs/puppet-mode.el b/ext/emacs/puppet-mode.el
index 11fcfea..0a7ee1a 100644
--- a/ext/emacs/puppet-mode.el
+++ b/ext/emacs/puppet-mode.el
@@ -2,11 +2,10 @@
 ;;; puppet-mode.el
 ;;; 
 ;;; Author: lutter
-;;; Author: Russ Allbery <rra at stanford.edu>
-;;;
 ;;; Description: A simple mode for editing puppet manifests
+;;;
 
-(defconst puppet-mode-version "0.2")
+(defconst puppet-mode-version "0.1")
 
 (defvar puppet-mode-abbrev-table nil
   "Abbrev table in use in puppet-mode buffers.")
@@ -57,43 +56,11 @@
   "*Indentation column of comments."
   :type 'integer :group 'puppet)
 
-(defun puppet-count-matches (re start end)
-  "The same as Emacs 22 count-matches, for portability to other versions
-of Emacs."
-  (save-excursion
-    (let ((n 0))
-      (goto-char start)
-      (while (re-search-forward re end t) (setq n (1+ n)))
-      n)))
-
 (defun puppet-comment-line-p ()
   "Return non-nil iff this line is a comment."
   (save-excursion
-    (save-match-data
-      (beginning-of-line)
-      (looking-at (format "\\s-*%s" comment-start)))))
-
-(defun puppet-block-indent ()
-  "If point is in a block, return the indentation of the first line of that
-block (the line containing the opening brace).  Used to set the indentation
-of the closing brace of a block."
-  (save-excursion
-    (save-match-data
-      (let ((opoint (point))
-            (apoint (search-backward "{" nil t)))
-        (when apoint
-          ;; This is a bit of a hack and doesn't allow for strings.  We really
-          ;; want to parse by sexps at some point.
-          (let ((close-braces (puppet-count-matches "}" apoint opoint))
-                (open-braces 0))
-            (while (and apoint (> close-braces open-braces))
-              (setq apoint (search-backward "{" nil t))
-              (when apoint
-                (setq close-braces (puppet-count-matches "}" apoint opoint))
-                (setq open-braces (1+ open-braces)))))
-          (if apoint
-              (current-indentation)
-            nil))))))
+    (beginning-of-line)
+    (looking-at (format "\\s-*%s" comment-start))))
 
 (defun puppet-in-array ()
   "If point is in an array, return the position of the opening '[' of
@@ -103,16 +70,15 @@ that array, else return nil."
       (let ((opoint (point))
             (apoint (search-backward "[" nil t)))
         (when apoint
-          ;; This is a bit of a hack and doesn't allow for strings.  We really
-          ;; want to parse by sexps at some point.
-          (let ((close-brackets (puppet-count-matches "]" apoint opoint))
-                (open-brackets 0))
-            (while (and apoint (> close-brackets open-brackets))
-              (setq apoint (search-backward "[" nil t))
-              (when apoint
-                (setq close-brackets (puppet-count-matches "]" apoint opoint))
-                (setq open-brackets (1+ open-brackets)))))
-          apoint)))))
+          ;; An array opens before point.  If it doesn't close before
+          ;; point, then point must be in it.
+          ;; ### TODO: of course, the '[' could be in a string literal,
+          ;; ### in which case this whole idea is bogus.  But baby
+          ;; ### steps, baby steps.  A more robust strategy might be
+          ;; ### to walk backwards by sexps, until hit a wall, then
+          ;; ### inspect the nature of that wall.
+          (if (= (count-matches "\\]" apoint opoint) 0)
+              apoint))))))
 
 (defun puppet-in-include ()
   "If point is in a continued list of include statements, return the position
@@ -124,14 +90,15 @@ of the initial include plus puppet-include-indent."
         (while not-found
           (forward-line -1)
           (cond
-           ((bobp)
-            (setq not-found nil))
-           ((looking-at "^\\s-*include\\s-+.*,\\s-*$")
-            (setq include-column
-                  (+ (current-indentation) puppet-include-indent))
-            (setq not-found nil))
-           ((not (looking-at ".*,\\s-*$"))
-            (setq not-found nil))))
+             ((puppet-comment-line-p)
+              (if (bobp)
+                  (setq not-found nil)))
+             ((looking-at "^\\s-*include\\s-+.*,\\s-*$")
+              (setq include-column
+                    (+ (current-indentation) puppet-include-indent))
+              (setq not-found nil))
+             ((not (looking-at ".*,\\s-*$"))
+              (setq not-found nil))))
         include-column))))
 
 (defun puppet-indent-line ()
@@ -143,7 +110,6 @@ of the initial include plus puppet-include-indent."
     (let ((not-indented t)
           (array-start (puppet-in-array))
           (include-start (puppet-in-include))
-          (block-indent (puppet-block-indent))
           cur-indent)
       (cond
        (array-start
@@ -180,11 +146,18 @@ of the initial include plus puppet-include-indent."
           (setq cur-indent (current-column))))
        (include-start
         (setq cur-indent include-start))
-       ((and (looking-at "^\\s-*}\\s-*$") block-indent)
-        ;; This line contains only a closing brace and we're at the inner
-        ;; block, so we should indent it matching the indentation of the
-        ;; opening brace of the block.
-        (setq cur-indent block-indent))
+       ((looking-at "^[^{\n]*}")
+        ;; This line contains the end of a block, but the block does
+        ;; not also begin on this line, so decrease the indentation.
+        (save-excursion
+          (forward-line -1)
+          (if (looking-at "^.*}")
+              (progn
+                (setq cur-indent (- (current-indentation) puppet-indent-level))
+                (setq not-indented nil))
+            (setq cur-indent (- (current-indentation) puppet-indent-level))))
+        (if (< cur-indent 0)     ; We can't indent past the left margin
+            (setq cur-indent 0)))
        (t
         ;; Otherwise, we did not start on a block-ending-only line.
         (save-excursion
@@ -192,135 +165,30 @@ of the initial include plus puppet-include-indent."
           (while not-indented
             (forward-line -1)
             (cond
-             ;; Comment lines are ignored unless we're at the start of the
-             ;; buffer.
              ((puppet-comment-line-p)
               (if (bobp)
-                  (setq not-indented nil)))
-
-             ;; Brace or paren on a line by itself will already be indented to
-             ;; the right level, so we can cheat and stop there.
-             ((looking-at "^\\s-*[\)}]\\s-*")
+                  (setq not-indented nil)
+                ;; else ignore the line and continue iterating backwards
+                ))
+             ((looking-at "^.*}") ; indent at the level of the END_ token
               (setq cur-indent (current-indentation))
               (setq not-indented nil))
-
-             ;; Brace or paren not on a line by itself will be indented one
-             ;; level too much, but don't catch cases where the block is
-             ;; started and closed on the same line.
-             ((looking-at "^[^\n\({]*[\)}]\\s-*$")
-              (setq cur-indent (- (current-indentation) puppet-indent-level))
-              (setq not-indented nil))
-
-             ;; Indent by one level more than the start of our block.  We lose
-             ;; if there is more than one block opened and closed on the same
-             ;; line but it's still unbalanced; hopefully people don't do that.
-             ((looking-at "^.*{[^\n}]*$")
-              (setq cur-indent (+ (current-indentation) puppet-indent-level)) 
-              (setq not-indented nil))
-
-             ;; Indent by one level if the line ends with an open paren.
-             ((looking-at "^.*\(\\s-*$")
+             ((looking-at "^.*{") ; indent an extra level
               (setq cur-indent (+ (current-indentation) puppet-indent-level)) 
               (setq not-indented nil))
-
-             ;; Semicolon ends a block for a resource when multiple resources
-             ;; are defined in the same block, but try not to get the case of
-             ;; a complete resource on a single line wrong.
-             ((looking-at "^\\([^'\":\n]\\|\"[^\n\"]*\"\\|'[^\n']'\\)**;\\s-*$")
+             ((looking-at "^.*;\\s-*$") ; Semicolon ends a nested resource
               (setq cur-indent (- (current-indentation) puppet-indent-level))
               (setq not-indented nil))
-
-             ;; Indent an extra level after : since it introduces a resource.
-             ((looking-at "^.*:\\s-*$")
+             ((looking-at "^.*:\\s-*$") ; indent an extra level after :
               (setq cur-indent (+ (current-indentation) puppet-indent-level))
               (setq not-indented nil))
-
-             ;; Start of buffer.
              ((bobp)
-              (setq not-indented nil)))))
-
-        ;; If this line contains only a closing paren, we should lose one
-        ;; level of indentation.
-        (if (looking-at "^\\s-*\)\\s-*$")
-            (setq cur-indent (- cur-indent puppet-indent-level)))))
-
-      ;; We've figured out the indentation, so do it.
-      (if (and cur-indent (> cur-indent 0))
+              (setq not-indented nil))
+             )))))
+      (if cur-indent
           (indent-line-to cur-indent)
         (indent-line-to 0)))))
 
-(defvar puppet-font-lock-syntax-table
-  (let* ((tbl (copy-syntax-table puppet-mode-syntax-table)))
-    (modify-syntax-entry ?_ "w" tbl)
-    tbl))
-
-(defvar puppet-font-lock-keywords
-  (list
-   ;; defines, classes, and nodes
-   '("^\\s *\\(class\\|define\\|node\\)\\s +\\([^( \t\n]+\\)"
-     2 font-lock-function-name-face)
-   ;; inheritence
-   '("\\s +inherits\\s +\\([^( \t\n]+\\)"
-     1 font-lock-function-name-face)
-   ;; include
-   '("\\(^\\|\\s +\\)include\\s +\\(\\([a-zA-Z0-9:_-]+\\(,[ \t\n]*\\)?\\)+\\)"
-     2 font-lock-reference-face)
-   ;; keywords
-   (cons (concat
-          "\\b\\(\\("
-          (mapconcat
-           'identity
-           '("alert"
-             "case"
-             "class"
-             "crit"
-             "debug"
-             "default"
-             "define"
-             "defined"
-             "else"
-             "emerg"
-             "err"
-             "fail"
-             "false"
-             "file"
-             "filebucket"
-             "generate"
-             "if"
-             "import"
-             "include"
-             "info"
-             "inherits"
-             "node"
-             "notice"
-             "realize"
-             "search"
-             "tag"
-             "tagged"
-             "template"
-             "true"
-             "warning"
-             )
-           "\\|")
-          "\\)\\>\\)")
-         1)
-     ;; variables
-     '("\\(^\\|[^_:.@$]\\)\\b\\(true\\|false\\)\\>"
-       2 font-lock-variable-name-face)
-     '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W"
-       1 font-lock-variable-name-face)
-     '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\|:\\)+"
-       0 font-lock-variable-name-face)
-     ;; usage of types
-     '("^\\s *\\([a-zA-Z_-]+\\)\\s +{"
-       1 font-lock-type-face)
-     ;; overrides and type references
-     '("\\s +\\([A-Z][a-zA-Z_:-]*\\)\\["
-       1 font-lock-type-face)
-     ;; general delimited string
-     '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
-       (2 font-lock-string-face)))
-  "*Additional expressions to highlight in puppet mode.")
 
 ;;;###autoload
 (defun puppet-mode ()
@@ -345,14 +213,97 @@ The variable puppet-indent-level controls the amount of indentation.
   (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
   (set (make-local-variable 'paragraph-start) "\f\\|[ 	]*$")
   (set (make-local-variable 'paragraph-separate) "[ 	\f]*$")
+  (run-hooks 'puppet-mode-hook))
+
+(cond
+ ((featurep 'font-lock)
   (or (boundp 'font-lock-variable-name-face)
       (setq font-lock-variable-name-face font-lock-type-face))
-  (set (make-local-variable 'font-lock-keywords) puppet-font-lock-keywords)
-  (set (make-local-variable 'font-lock-multiline) t)
-  (set (make-local-variable 'font-lock-defaults)
-       '((puppet-font-lock-keywords) nil nil))
-  (set (make-local-variable 'font-lock-syntax-table)
-       puppet-font-lock-syntax-table)
-  (run-hooks 'puppet-mode-hook))
+
+  (setq puppet-font-lock-syntactic-keywords
+        '(
+          ("\\(^\\|[=(,~?:;]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"
+           (4 (7 . ?/))
+           (6 (7 . ?/)))
+          ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
+          ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
+
+  (cond ((featurep 'xemacs)
+         (put 'puppet-mode 'font-lock-defaults
+              '((puppet-font-lock-keywords)
+                nil nil nil
+                beginning-of-line
+                (font-lock-syntactic-keywords
+                 . puppet-font-lock-syntactic-keywords))))
+        (t
+         (add-hook 'puppet-mode-hook
+            '(lambda ()
+               (make-local-variable 'font-lock-defaults)
+               (make-local-variable 'font-lock-keywords)
+               (make-local-variable 'font-lock-syntax-table)
+               (make-local-variable 'font-lock-syntactic-keywords)
+               (setq font-lock-defaults '((puppet-font-lock-keywords) nil nil))
+               (setq font-lock-keywords puppet-font-lock-keywords)
+               (setq font-lock-syntax-table puppet-font-lock-syntax-table)
+               (setq font-lock-syntactic-keywords puppet-font-lock-syntactic-keywords)))))
+
+  (defvar puppet-font-lock-syntax-table
+    (let* ((tbl (copy-syntax-table puppet-mode-syntax-table)))
+      (modify-syntax-entry ?_ "w" tbl)
+      tbl))
+
+  (defvar puppet-font-lock-keywords
+    (list
+     ;; defines
+     '("^\\s *\\(define\\|node\\|class\\)\\s +\\([^( \t\n]+\\)"
+       2 font-lock-function-name-face)
+     '("\\s +inherits\\s +\\([^( \t\n]+\\)"
+       1 font-lock-function-name-face)
+     ;; include
+     '("^\\s *include\\s +\\([^( \t\n,]+\\)"
+       1 font-lock-reference-face)
+     ;; hack to catch continued includes
+     '("^\\s *\\([a-zA-Z0-9:_-]+\\),?\\s *$"
+       1 font-lock-reference-face)
+     ;; keywords
+     (cons (concat
+            "\\b\\(\\("
+            (mapconcat
+             'identity
+             '("case"
+               "class"
+               "default"
+               "define"
+               "false"
+               "import"
+               "include"
+               "inherits"
+               "node"
+               "realize"
+               "true"
+               )
+             "\\|")
+            "\\)\\>\\)")
+           1)
+     ;; variables
+     '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
+       2 font-lock-variable-name-face)
+     ;; variables
+     '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W"
+       1 font-lock-variable-name-face)
+     '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+"
+       0 font-lock-variable-name-face)
+     ;; usage of types
+     '("^\\s +\\([a-zA-Z_-]+\\)\\s +{" 
+       1 font-lock-type-face)
+     ;; overrides
+     '("^\\s +\\([a-zA-Z_-]+\\)\\["
+       1 font-lock-type-face)
+     ;; general delimited string
+     '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
+       (2 font-lock-string-face))
+     )
+    "*Additional expressions to highlight in puppet mode."))
+ )
 
 (provide 'puppet-mode)
diff --git a/ext/ldap/puppet.schema b/ext/ldap/puppet.schema
index a7a5f46..d8dc426 100644
--- a/ext/ldap/puppet.schema
+++ b/ext/ldap/puppet.schema
@@ -17,11 +17,6 @@ attributetype ( 1.1.3.11 NAME 'environment'
 	EQUALITY caseIgnoreIA5Match
 	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
 
-attributetype ( 1.1.3.12 NAME 'puppetvar'
-	DESC 'A variable setting for puppet'
-	EQUALITY caseIgnoreIA5Match
-	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
 objectclass ( 1.1.1.2 NAME 'puppetClient' SUP top AUXILIARY
 	DESC 'Puppet Client objectclass'
-	MAY ( puppetclass $ parentnode $ environment $ puppetvar ))
+	MAY ( puppetclass $ parentnode $ environment ))
diff --git a/ext/module_puppet b/ext/module_puppet
index 8609e44..e4a680e 100755
--- a/ext/module_puppet
+++ b/ext/module_puppet
@@ -138,9 +138,8 @@ server = nil
     end
 end
 
-if Puppet.settings.print_configs?
-        exit(Puppet.settings.print_configs ? 0 : 1)
-end
+Puppet.genconfig
+Puppet.genmanifest
 
 unless ARGV.length > 0
     $stderr.puts "You must pass a script to parse"
@@ -180,7 +179,7 @@ node.classes = classes
 
 begin
     # Compile our configuration
-    catalog = Puppet::Node::Catalog.find(node.name, :use_node => node)
+    catalog = Puppet::Node::Catalog.find(node.name, :node => node)
 rescue => detail
     if Puppet[:trace]
         puts detail.backtrace
diff --git a/ext/passenger/README b/ext/passenger/README
deleted file mode 100644
index fcdcb91..0000000
--- a/ext/passenger/README
+++ /dev/null
@@ -1,63 +0,0 @@
-
-PUPPETMASTER INSIDE APACHE & PASSENGER
-======================================
-
-This is about running a puppetmaster inside Apache.
-
-Please also see the docs at http://reductivelabs.com/trac/puppet/wiki/UsingPassenger
-for further information.
-
-
-WHAT IS IT?
-===========
-
-Passenger [1] (AKA mod_rails or mod_rack) is an Apache 2.x Extension for 
-serving Rails or Rack applications.
-
-This extension allows running a puppetmasterd as a Rack application;
-it has only been tested with Passenger.
-
-
-SHORT INSTALLATION INSTRUCTIONS
-===============================
-
-Make sure puppetmasterd ran at least once, so the SSL certificates
-got set up. 
-
-Install Rack:
-  gem install -v 0.4.0 rack
-
-Install Apache and Passenger:
-  apt-get install apache2
-  gem install passenger
-  passenger-install-apache2-module
-  (See the Passenger installation instructions [2] for details.)
-
-Enable Apache modules:
-  a2enmod ssl
-  a2enmod headers
-
-Configure Apache:
-  cp apache2.conf /etc/apache2/conf.d/puppetmasterd
-  vim /etc/apache2/conf.d/puppetmasterd (replace the server hostnames)
-
-Install the rack application [3]:
-  mkdir -p /usr/share/puppet/rack/puppetmasterd
-  mkdir /usr/share/puppet/rack/puppetmasterd/public /usr/share/puppet/rack/puppetmasterd/tmp
-  cp config.ru /usr/share/puppet/rack/puppetmasterd
-  chown puppet /usr/share/puppet/rack/puppetmasterd/config.ru
-
-Go:
-/etc/init.d/apache2 restart
-
-
-
-[1] http://www.modrails.com/
-
-[2] http://www.modrails.com/install.html
-
-[3] Passenger will not let applications run as root or the Apache user, 
-instead an implicit setuid will be done, to the user whom owns 
-config.ru. Therefore, config.ru shall be owned by the puppet user.
-
-
diff --git a/ext/passenger/apache2.conf b/ext/passenger/apache2.conf
deleted file mode 100644
index 6a8a974..0000000
--- a/ext/passenger/apache2.conf
+++ /dev/null
@@ -1,29 +0,0 @@
-Listen 8140
-<VirtualHost *:8140>
-	SSLEngine on
-	SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
-	SSLCertificateFile      /var/lib/puppet/ssl/certs/puppet-server.inqnet.at.pem
-	SSLCertificateKeyFile   /var/lib/puppet/ssl/private_keys/puppet-server.inqnet.at.pem
-	SSLCertificateChainFile /var/lib/puppet/ssl/ca/ca_crt.pem
-	SSLCACertificateFile    /var/lib/puppet/ssl/ca/ca_crt.pem
-	# If Apache complains about invalid signatures on the CRL, you can try disabling
-	# CRL checking by commenting the next line.
-	SSLCARevocationFile     /var/lib/puppet/ssl/ca/ca_crl.pem
-	SSLVerifyClient optional
-	SSLVerifyDepth  1
-	SSLOptions +StdEnvVars
-
-	# The following client headers allow the same configuration to work with Pound.
-	RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
-	RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
-	RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
-
-	RackAutoDetect On
-	DocumentRoot /usr/share/puppet/rack/puppetmasterd/public/
-	<Directory /usr/share/puppet/rack/puppetmasterd/>
-		Options None
-		AllowOverride None
-		Order allow,deny
-		allow from all
-	</Directory>
-</VirtualHost>
diff --git a/ext/passenger/config.ru b/ext/passenger/config.ru
deleted file mode 100644
index 8608292..0000000
--- a/ext/passenger/config.ru
+++ /dev/null
@@ -1,40 +0,0 @@
-# Author: Christian Hofstaedtler <hofstaedtler at inqnet.at>
-# Copyright (c) 2007 Luke Kanies, 2008 Christian Hofstaedtler
-#
-# This file is mostly based on puppetmasterd, which is part of
-# the standard puppet distribution.
-
-require 'rack'
-require 'puppet'
-require 'puppet/network/http_server/rack'
-
-# startup code from bin/puppetmasterd
-Puppet.parse_config
-Puppet::Util::Log.level = :info
-Puppet::Util::Log.newdestination(:syslog)
-# A temporary solution, to at least make the master work for now.
-Puppet::Node::Facts.terminus_class = :yaml
-# Cache our nodes in yaml.  Currently not configurable.
-Puppet::Node.cache_class = :yaml
-
-# The list of handlers running inside this puppetmaster
-handlers = {
-	:Status => {},
-	:FileServer => {},
-	:Master => {},
-	:CA => {},
-	:FileBucket => {},
-	:Report => {}
-}
-
-# Fire up the Rack-Server instance
-server = Puppet::Network::HTTPServer::Rack.new(handlers)
-
-# prepare the rack app
-app = proc do |env|
-	server.process(env)
-end
-
-# Go.
-run app
-
diff --git a/ext/puppetlast b/ext/puppetlast
deleted file mode 100755
index e52529d..0000000
--- a/ext/puppetlast
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env ruby
-# Puppetlast, a script to output the last check-in time of nodes. Also outputs the cached configuration state, if expired or not.
-#
-# AJ "Fujin" Christensen <aj at junglist.gen.nz>
-#
-require 'puppet'
-
-Puppet[:config] = "/etc/puppet/puppet.conf"
-Puppet.parse_config
-Puppet[:name] = "puppetmasterd"
-Puppet::Node::Facts.terminus_class = :yaml
-
-Puppet::Node::Facts.search("*").sort { |a,b| a.name <=> b.name }.each do |node|
-  puts "#{node.name} #{node.expired? ? 'cached expired, ' : ''}checked in #{((Time.now - node.values[:_timestamp]) / 60).floor} minutes ago"
-end
diff --git a/ext/puppetstoredconfigclean.rb b/ext/puppetstoredconfigclean.rb
deleted file mode 100644
index f286df2..0000000
--- a/ext/puppetstoredconfigclean.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env ruby
-
-# Script to clean up stored configs for (a) given host(s)
-#
-# Credits:
-# Script was taken from http://reductivelabs.com/trac/puppet/attachment/wiki/UsingStoredConfiguration/kill_node_in_storedconfigs_db.rb
-# which haven been initially posted by James Turnbull
-# duritong adapted and improved the script a bit.
-
-require 'getoptlong'
-config = '/etc/puppet/puppet.conf'
-
-def printusage(error_code)
-	puts "Usage: #{$0} [ list of hostnames as stored in hosts table ]"
-	puts "\n Options:"
-	puts "--config <puppet config file>"
-	exit(error_code)
-end
-
-opts = GetoptLong.new(
-        [ "--config",     "-c",   GetoptLong::REQUIRED_ARGUMENT ],	
-        [ "--help",        "-h",   GetoptLong::NO_ARGUMENT ],
-        [ "--usage",       "-u",   GetoptLong::NO_ARGUMENT ],
-        [ "--version",     "-v",   GetoptLong::NO_ARGUMENT ]
-)
-
-begin
-	opts.each do |opt, arg|
-    	case opt
-        	when "--config"
-				config = arg
-
-            when "--help"
-            	printusage(0)
-
-            when "--usage"
-            	printusage(0)
-
-            when "--version"
-        		puts "%s" % Puppet.version
-				exit
-		end
-	end
-rescue GetoptLong::InvalidOption => detail
-    $stderr.puts "Try '#{$0} --help'"
-    exit(1)
-end
-
-printusage(1) unless ARGV.size > 0
-
-require 'puppet/rails'
-Puppet[:config] = config
-Puppet.parse_config
-pm_conf = Puppet.settings.instance_variable_get(:@values)[:puppetmasterd]
-
-adapter = pm_conf[:dbadapter]
-args = {:adapter => adapter, :log_level => pm_conf[:rails_loglevel]}
-
-case adapter
-  when "sqlite3":
-    args[:dbfile] = pm_conf[:dblocation]
-  when "mysql", "postgresql":
-    args[:host]     = pm_conf[:dbserver] unless pm_conf[:dbserver].to_s.empty?
-    args[:username] = pm_conf[:dbuser] unless pm_conf[:dbuser].to_s.empty?
-    args[:password] = pm_conf[:dbpassword] unless pm_conf[:dbpassword].to_s.empty?
-    args[:database] = pm_conf[:dbname] unless pm_conf[:dbname].to_s.empty?
-    socket          = pm_conf[:dbsocket]
-    args[:socket]   = socket unless socket.to_s.empty?
-  else
-    raise ArgumentError, "Invalid db adapter %s" % adapter
-end
-
-args[:database] = "puppet" unless not args[:database].to_s.empty?
-
-ActiveRecord::Base.establish_connection(args)
-
-ARGV.each { |hostname|
-    if @host = Puppet::Rails::Host.find_by_name(hostname.strip)
-        print "Killing #{hostname}..."
-        $stdout.flush
-        @host.destroy
-        puts "done."
-    else
-        puts "Can't find host #{hostname}."
-    end
-}
-exit 0
diff --git a/install.rb b/install.rb
index 3fa3822..087c3c8 100755
--- a/install.rb
+++ b/install.rb
@@ -60,7 +60,6 @@ rescue
 end
 
 PREREQS = %w{openssl facter xmlrpc/client xmlrpc/server cgi}
-MIN_FACTER_VERSION = 1.5
 
 InstallOptions = OpenStruct.new
 
@@ -79,7 +78,7 @@ rdoc  = glob(%w{bin/* sbin/* lib/**/*.rb README README-library CHANGELOG TODO In
 ri    = glob(%w(bin/*.rb sbin/* lib/**/*.rb)).reject { |e| e=~ /\.(bat|cmd)$/ }
 man   = glob(%w{man/man8/*})
 libs  = glob(%w{lib/**/*.rb lib/**/*.py})
-tests = glob(%w{test/**/*.rb})
+tests = glob(%w{tests/**/*.rb})
 
 def do_bins(bins, target, strip = 's?bin/')
   bins.each do |bf|
@@ -103,11 +102,11 @@ def do_man(man, strip = 'man/')
     omf = File.join(InstallOptions.man_dir, mf.gsub(/#{strip}/, ''))
     om = File.dirname(omf)
     File.makedirs(om, true)
-    File.chmod(0755, om)
+    File.chmod(0644, om)
     File.install(mf, omf, 0644, true)
     gzip = %x{which gzip}
     gzip.chomp!
-    %x{#{gzip} -f #{omf}}
+    %x{#{gzip} #{omf}}
   end
 end
 
@@ -116,15 +115,6 @@ def check_prereqs
     PREREQS.each { |pre|
         begin
             require pre
-            if pre == "facter"
-              # to_f isn't quite exact for strings like "1.5.1" but is good
-              # enough for this purpose.
-              facter_version = Facter.version.to_f
-              if facter_version < MIN_FACTER_VERSION
-                puts "Facter version: %s; minimum required: %s; cannot install" % [facter_version, MIN_FACTER_VERSION]
-                exit -1
-              end
-            end
         rescue LoadError
             puts "Could not load %s; cannot install" % pre
             exit -1
@@ -176,21 +166,6 @@ def prepare_installation
     opts.on('--[no-]tests', 'Prevents the execution of unit tests.', 'Default on.') do |ontest|
       InstallOptions.tests = ontest
     end
-    opts.on('--destdir[=OPTIONAL]', 'Installation prefix for all targets', 'Default essentially /') do |destdir|
-      InstallOptions.destdir = destdir
-    end
-    opts.on('--bindir[=OPTIONAL]', 'Installation directory for binaries', 'overrides Config::CONFIG["bindir"]') do |bindir|
-      InstallOptions.bindir = bindir
-    end
-    opts.on('--sbindir[=OPTIONAL]', 'Installation directory for system binaries', 'overrides Config::CONFIG["sbindir"]') do |sbindir|
-      InstallOptions.sbindir = sbindir
-    end
-    opts.on('--sitelibdir[=OPTIONAL]', 'Installation directory for libraries', 'overrides Config::CONFIG["sitelibdir"]') do |sitelibdir|
-      InstallOptions.sitelibdir = sitelibdir
-    end
-    opts.on('--mandir[=OPTIONAL]', 'Installation directory for man pages', 'overrides Config::CONFIG["mandir"]') do |mandir|
-      InstallOptions.mandir = mandir
-    end
     opts.on('--quick', 'Performs a quick installation. Only the', 'installation is done.') do |quick|
       InstallOptions.rdoc   = false
       InstallOptions.ri     = false
@@ -215,73 +190,34 @@ def prepare_installation
   version = [Config::CONFIG["MAJOR"], Config::CONFIG["MINOR"]].join(".")
   libdir = File.join(Config::CONFIG["libdir"], "ruby", version)
 
-  # Mac OS X 10.5 declares bindir and sbindir as
-  # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin
-  # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/sbin
-  # which is not generally where people expect executables to be installed
-  if RUBY_PLATFORM == "universal-darwin9.0"
-    Config::CONFIG['bindir'] = "/usr/bin"
-    Config::CONFIG['sbindir'] = "/usr/sbin"
-  end
-  
-  if not InstallOptions.bindir.nil?
-    bindir = InstallOptions.bindir
-  else
-    bindir = Config::CONFIG['bindir']
-  end
-  
-  if not InstallOptions.sbindir.nil?
-    sbindir = InstallOptions.sbindir
-  else
-    sbindir = Config::CONFIG['sbindir']
-  end
-  
-  if not InstallOptions.sitelibdir.nil?
-    sitelibdir = InstallOptions.sitelibdir
-  else
-    sitelibdir = Config::CONFIG["sitelibdir"]
+  sitelibdir = Config::CONFIG["sitelibdir"]
+  if sitelibdir.nil?
+    sitelibdir = $:.find { |x| x =~ /site_ruby/ }
     if sitelibdir.nil?
-      sitelibdir = $:.find { |x| x =~ /site_ruby/ }
-      if sitelibdir.nil?
-        sitelibdir = File.join(libdir, "site_ruby")
-      elsif sitelibdir !~ Regexp.quote(version)
-        sitelibdir = File.join(sitelibdir, version)
-      end
+      sitelibdir = File.join(libdir, "site_ruby")
+    elsif sitelibdir !~ Regexp.quote(version)
+      sitelibdir = File.join(sitelibdir, version)
     end
   end
-  
-  if not InstallOptions.mandir.nil?
-    mandir = InstallOptions.mandir
-  else
-    mandir = Config::CONFIG['mandir'] 
-  end
 
-  # To be deprecated once people move over to using --destdir option
   if (destdir = ENV['DESTDIR'])
-    bindir = "#{destdir}#{bindir}"
-    sbindir = "#{destdir}#{sbindir}"
-    mandir = "#{destdir}#{mandir}"
-    sitelibdir = "#{destdir}#{sitelibdir}"
-
-    FileUtils.makedirs(bindir)
-    FileUtils.makedirs(sbindir)
-    FileUtils.makedirs(mandir)
-    FileUtils.makedirs(sitelibdir)
-  # This is the new way forward
-  elsif (destdir = InstallOptions.destdir)
-    bindir = "#{destdir}#{bindir}"
-    sbindir = "#{destdir}#{sbindir}"
-    mandir = "#{destdir}#{mandir}"
+    bindir = "#{destdir}#{Config::CONFIG['bindir']}"
+    sbindir = "#{destdir}#{Config::CONFIG['sbindir']}"
+    mandir = "#{destdir}#{Config::CONFIG['mandir']}"
     sitelibdir = "#{destdir}#{sitelibdir}"
+    tmpdirs << bindir
 
     FileUtils.makedirs(bindir)
     FileUtils.makedirs(sbindir)
     FileUtils.makedirs(mandir)
     FileUtils.makedirs(sitelibdir)
+  else
+    bindir = Config::CONFIG['bindir']
+    sbindir = Config::CONFIG['sbindir']
+    mandir = Config::CONFIG['mandir']
+    tmpdirs << Config::CONFIG['bindir']
   end
 
-  tmpdirs << bindir
-
   InstallOptions.tmp_dirs = tmpdirs.compact
   InstallOptions.site_dir = sitelibdir
   InstallOptions.bin_dir  = bindir
@@ -438,7 +374,7 @@ EOS
 check_prereqs
 prepare_installation
 
-#run_tests(tests) if InstallOptions.tests
+run_tests(tests) if InstallOptions.tests
 #build_rdoc(rdoc) if InstallOptions.rdoc
 #build_ri(ri) if InstallOptions.ri
 #build_man(bins) if InstallOptions.man
diff --git a/lib/puppet.rb b/lib/puppet.rb
index acf3246..66a52f9 100644
--- a/lib/puppet.rb
+++ b/lib/puppet.rb
@@ -25,7 +25,7 @@ require 'puppet/util/suidmanager'
 # it's also a place to find top-level commands like 'debug'
 
 module Puppet
-    PUPPETVERSION = '0.24.6'
+    PUPPETVERSION = '0.24.4'
 
     def Puppet.version
         return PUPPETVERSION
@@ -117,6 +117,49 @@ module Puppet
     # Load all of the configuration parameters.
     require 'puppet/defaults'
 
+    # Prints the contents of a config file with the available config elements, or it
+    # prints a single value of a config element.
+    def self.genconfig
+        if Puppet[:configprint] != ""
+            val = Puppet[:configprint]
+            if val == "all"
+                hash = {}
+                Puppet.settings.each do |name, obj|
+                    val = obj.value
+                    case val
+                    when true, false, "": val = val.inspect
+                    end
+                    hash[name] = val
+                end
+                hash.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, val|
+                    puts "%s = %s" % [name, val]
+                end
+            elsif val =~ /,/
+                val.split(/\s*,\s*/).sort.each do |v|
+                    if Puppet.settings.include?(v)
+                        puts "%s = %s" % [v, Puppet[v]]
+                    else
+                        puts "invalid parameter: %s" % v
+                        exit(1)
+                    end
+                end
+            else
+                val.split(/\s*,\s*/).sort.each do |v|
+                    if Puppet.settings.include?(v)
+                        puts Puppet[val]
+                    else
+                        puts "invalid parameter: %s" % v
+                        exit(1)
+                    end
+                end
+            end
+            exit(0)
+        end
+        if Puppet[:genconfig]
+            puts Puppet.settings.to_config
+            exit(0)
+        end
+    end
 
     def self.genmanifest
         if Puppet[:genmanifest]
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index e1b6dc4..eed1a00 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -69,6 +69,8 @@ module Puppet
         :rundir => { 
             :default => rundir,
             :mode => 01777,
+            :owner => "$user",
+            :group => "$group",
             :desc => "Where Puppet PID files are kept."
         },
         :genconfig => [false,
@@ -122,11 +124,16 @@ module Puppet
             namespaces and methods.  This can be used as a coarse-grained
             authorization system for both ``puppetd`` and ``puppetmasterd``."
         ],
+        :environments => ["production,development", "The valid environments for Puppet clients.
+            This is more useful as a server-side setting than client, but any
+            environment chosen must be in this list.  Values should be
+            separated by a comma."],
         :environment => {:default => "production", :desc => "The environment Puppet is running in.  For clients
             (e.g., ``puppetd``) this determines the environment itself, which
             is used to find modules and much more.  For servers (i.e.,
             ``puppetmasterd``) this provides the default environment for nodes
-            we know nothing about."
+            we know nothing about.",
+            :hook => proc { |value| raise(ArgumentError, "Invalid environment %s" % value) unless Puppet::Node::Environment.valid?(value) }
         },
         :diff_args => ["", "Which arguments to pass to the diff command when printing differences between files."],
         :diff => ["diff", "Which diff command to use when printing differences between files."],
@@ -153,12 +160,8 @@ module Puppet
     end
 
     Puppet.setdefaults(:ssl,
-        # We have to downcase the fqdn, because the current ssl stuff (as oppsed to in master) doesn't have good facilities for 
-        # manipulating naming.
-        :certname => {:default => fqdn.downcase, :desc => "The name to use when handling certificates.  Defaults
-            to the fully qualified domain name.",
-            :call_on_define => true, # Call our hook with the default value, so we're always downcased
-            :hook => proc { |value| raise(ArgumentError, "Certificate names must be lower case; see #1168") unless value == value.downcase }},
+        :certname => [fqdn, "The name to use when handling certificates.  Defaults
+            to the fully qualified domain name."],
         :certdnsnames => ['', "The DNS names on the Server certificate as a colon-separated list.
             If it's anything other than an empty string, it will be used as an alias in the created
             certificate.  By default, only the server gets an alias set up, and only for 'puppet'."],
@@ -351,9 +354,7 @@ module Puppet
         # To make sure this directory is created before we try to use it on the server, we need
         # it to be in the server section (#1138).
         :yamldir => {:default => "$vardir/yaml", :owner => "$user", :group => "$user", :mode => "750",
-            :desc => "The directory in which YAML data is stored, usually in a subdirectory."},
-        :clientyamldir => {:default => "$vardir/client_yaml", :mode => "750",
-            :desc => "The directory in which client-side YAML data is stored."}
+            :desc => "The directory in which YAML data is stored, usually in a subdirectory."}
     )
 
     self.setdefaults(:puppetd,
@@ -411,10 +412,7 @@ module Puppet
         :ca_server => ["$server", "The server to use for certificate
             authority requests.  It's a separate server because it cannot
             and does not need to horizontally scale."],
-        :ca_port => ["$masterport", "The port to use for the certificate authority."],
-        :catalog_format => ["yaml", "What format to use to dump the catalog.  Only supports
-            'marshal' and 'yaml'.  Only matters on the client, since it asks the server
-            for a specific format."]
+        :ca_port => ["$masterport", "The port to use for the certificate authority."]
     )
         
     self.setdefaults(:filebucket,
@@ -507,11 +505,9 @@ module Puppet
 
     # Central fact information.
     self.setdefaults(:main,
-        :factpath => {:default => "$vardir/facts",
-            :desc => "Where Puppet should look for facts.  Multiple directories should
-                be colon-separated, like normal PATH variables.",
-            :call_on_define => true, # Call our hook with the default value, so we always get the value added to facter.
-            :hook => proc { |value| Facter.search(value) if Facter.respond_to?(:search) }},
+        :factpath => ["$vardir/facts",
+            "Where Puppet should look for facts.  Multiple directories should
+            be colon-separated, like normal PATH variables."],
         :factdest => ["$vardir/facts",
             "Where Puppet should store facts that it pulls down from the central
             server."],
@@ -626,10 +622,6 @@ module Puppet
         :ldapclassattrs => ["puppetclass",
             "The LDAP attributes to use to define Puppet classes.  Values
             should be comma-separated."],
-        :ldapstackedattrs => ["puppetvar",
-            "The LDAP attributes that should be stacked to arrays by adding
-            the values in all hierarchy elements of the tree.  Values
-            should be comma-separated."],
         :ldapattrs => ["all",
             "The LDAP attributes to include when querying LDAP for nodes.  All
             returned attributes are set as variables in the top-level scope.
@@ -659,8 +651,7 @@ module Puppet
     setdefaults(:parser,
         :lexical => [false, "Whether to use lexical scoping (vs. dynamic)."],
         :templatedir => ["$vardir/templates",
-            "Where Puppet looks for template files.  Can be a list of colon-seperated
-             directories."
+            "Where Puppet looks for template files."
         ]
     )
 
diff --git a/lib/puppet/event.rb b/lib/puppet/event.rb
new file mode 100644
index 0000000..c1928a3
--- /dev/null
+++ b/lib/puppet/event.rb
@@ -0,0 +1,28 @@
+require 'puppet'
+require 'puppet/util/methodhelper'
+require 'puppet/util/errors'
+
+module Puppet
+    # events are transient packets of information; they result in one or more (or none)
+    # subscriptions getting triggered, and then they get cleared
+    # eventually, these will be passed on to some central event system
+	class Event
+        include Puppet
+        include Puppet::Util::MethodHelper
+        include Puppet::Util::Errors
+        
+		attr_accessor :event, :source, :transaction
+
+        @@events = []
+
+		def initialize(args)
+		    set_options symbolize_options(args)
+		    requiredopts(:event, :source)
+		end
+
+        def to_s
+            @source.to_s + " -> " + self.event.to_s
+        end
+	end
+end
+
diff --git a/lib/puppet/executables/client/certhandler.rb b/lib/puppet/executables/client/certhandler.rb
deleted file mode 100644
index b041397..0000000
--- a/lib/puppet/executables/client/certhandler.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-
-module Puppet
-    module Executables
-        module Client
-            class CertHandler
-                attr_writer :wait_for_cert, :one_time
-                attr_reader :new_cert
-                
-                def initialize(wait_time, is_one_time)
-                    @wait_for_cert = wait_time
-                    @one_time = is_one_time
-                    @new_cert = false
-                end
-
-                # Did we just read a cert?
-                def new_cert?
-                    new_cert
-                end
-                
-                # Read, or retrieve if necessary, our certificate.  Returns true if we retrieved
-                # a new cert, false if the cert already exists.
-                def read_retrieve 
-                    #NOTE: ACS this is checking that a file exists, maybe next time just do that?
-                    unless read_cert 
-                        # If we don't already have the certificate, then create a client to
-                        # request one.  Use the special ca stuff, don't use the normal server and port.
-                        retrieve_cert
-                    end
-
-                    ! new_cert?
-                end
-
-                def retrieve_cert
-                    caclient = Puppet::Network::Client.ca.new()
-
-                    while true do
-                       begin
-                           if caclient.request_cert 
-                               break if read_new_cert
-                           else
-                               Puppet.notice "Did not receive certificate"
-                               if @one_time 
-                                   Puppet.notice "Set to run 'one time'; exiting with no certificate"
-                                   exit(1)
-                               end
-                           end
-                       rescue StandardError => detail
-                          Puppet.err "Could not request certificate: %s" % detail.to_s
-                          exit(23) if @one_time
-                       end
-
-                       sleep @wait_for_cert 
-                    end
-                end
-
-                def read_cert
-                    Puppet::Network::HttpPool.read_cert
-                end
-
-                def read_new_cert
-                    if Puppet::Network::HttpPool.read_cert
-                        # If we read it in, then we need to get rid of our existing http connection.
-                        # The @new_cert flag will help us do that, in that it provides a way
-                        # to notify that the cert status has changed.
-                        @new_cert = true
-                        Puppet.notice "Got signed certificate"
-                    else
-                        Puppet.err "Could not read certificates after retrieving them"
-                        exit(34) if @one_time
-                    end
-
-                    return @new_cert
-                end
-            end
-        end
-    end
-end
diff --git a/lib/puppet/external/nagios/grammar.ry b/lib/puppet/external/nagios/grammar.ry
new file mode 100644
index 0000000..f50818f
--- /dev/null
+++ b/lib/puppet/external/nagios/grammar.ry
@@ -0,0 +1,188 @@
+# vim: syntax=ruby
+class Nagios::Parser
+
+token DEFINE NAME STRING PARAM LCURLY RCURLY VALUE RETURN COMMENT INLINECOMMENT
+
+rule
+decls: decl { return val[0] if val[0] }
+	| decls decl {
+		if val[1].nil?
+			result = val[0]
+		else
+			if val[0].nil?
+				result = val[1]
+			else
+				result = [ val[0], val[1] ].flatten
+			end
+		end
+	}
+	;
+
+decl: object { result = [val[0]] }
+	| RETURN { result = nil }
+	| comment
+	;
+	
+comment: COMMENT RETURN { result = nil }
+	;
+
+object: DEFINE NAME LCURLY RETURN vars RCURLY {
+		result = Nagios::Base.create(val[1],val[4])
+	}
+	;
+
+vars: var
+	| vars var {
+		val[1].each {|p,v|
+			val[0][p] = v
+		}
+		result = val[0]
+	}
+	;
+
+var: PARAM VALUE icomment returns { result = {val[0],val[1]} }
+	;
+
+returns:      RETURN
+            | returns RETURN
+            ;
+
+icomment: # nothing
+	| INLINECOMMENT
+	;
+
+end
+
+----inner
+
+def parse(src)
+	@src = src
+
+	# state variables
+	@invar = false
+	@inobject = false
+	@done = false
+
+	@line = 0
+	@yydebug = true
+
+    begin
+        do_parse
+    rescue SyntaxError
+        $stderr.print "#{$!}\n"
+        exit
+    end
+end
+
+# The lexer.  Very simple.
+def token
+	@src.sub!(/\A\n/,'')
+	if $&
+		@line += 1
+		return [ :RETURN, "\n" ]
+	end
+
+	if @done
+		return nil
+	end
+	yytext = String.new
+
+
+	# remove comments from this line
+	@src.sub!(/\A[ \t]*;.*\n/,"\n")
+	if $&
+		return [:INLINECOMMENT, ""]
+	end
+
+	@src.sub!(/\A#.*\n/,"\n")
+	if $&
+		return [:COMMENT, ""]
+	end
+
+	@src.sub!(/#.*/,'')
+
+	if @src.length == 0
+		@done = true
+		return [false, '$']
+	end
+
+	if @invar
+		@src.sub!(/\A[ \t]+/,'')
+		@src.sub!(/\A([^;\n]+)(\n|;)/,'\2')
+		if $1
+			yytext += $1
+		end
+		@invar = false
+		return [:VALUE, yytext]
+	else
+		@src.sub!(/\A[\t ]*(\S+)([\t ]*|$)/,'')
+        if $1
+            yytext = $1
+            case yytext
+            when 'define'
+                #puts "got define"
+                return [:DEFINE, yytext]
+            when '{'
+                #puts "got {"
+                @inobject = true
+                return [:LCURLY, yytext]
+            else
+                unless @inobject
+                    #puts "got type: #{yytext}"
+                    if yytext =~ /\W/
+                        giveback = yytext.dup
+                        giveback.sub!(/^\w+/,'')
+                        #puts "giveback " + giveback
+                        #puts "yytext " + yytext
+                        yytext.sub!(/\W.*$/,'')
+                        #puts "yytext " + yytext
+                        #puts "all [#{giveback} #{yytext} #{orig}]"
+                        @src = giveback + @src
+                    end
+                    return [:NAME, yytext]
+                else
+                    if yytext == '}'
+                        #puts "got closure: #{yytext}"
+                        @inobject = false
+                        return [:RCURLY, '}']
+                    end
+
+                    unless @invar
+                        @invar = true
+                        return [:PARAM, $1]
+                    else
+                    end
+                end
+            end
+        end
+	end
+end
+
+def next_token
+	token
+end
+
+def yydebug
+    1
+end
+
+def yywrap
+    0
+end
+
+def on_error(token, value, vstack )
+	msg = ""
+	unless value.nil?
+		msg = "line #{@line}: syntax error at '#{value}'"
+	else
+		msg = "line #{@line}: syntax error at '#{token}'"
+	end
+	unless @src.size > 0
+		msg = "line #{@line}: Unexpected end of file"
+	end
+	if token == '$end'.intern
+		puts "okay, this is silly"
+	else
+		raise SyntaxError, msg
+	end
+end
diff --git a/lib/puppet/external/nagios/makefile b/lib/puppet/external/nagios/makefile
new file mode 100644
index 0000000..fc14564
--- /dev/null
+++ b/lib/puppet/external/nagios/makefile
@@ -0,0 +1,9 @@
+all: parser.rb
+
+debug: parser.rb setdebug
+
+parser.rb: grammar.ry
+	racc -E -oparser.rb grammar.ry
+
+setdebug:
+	perl -pi -e 's{\@yydebug =.*$$}{\@yydebug = true}' parser.rb
diff --git a/lib/puppet/file_serving/fileset.rb b/lib/puppet/file_serving/fileset.rb
index 3cb7631..fe54350 100644
--- a/lib/puppet/file_serving/fileset.rb
+++ b/lib/puppet/file_serving/fileset.rb
@@ -20,7 +20,7 @@ class Puppet::FileServing::Fileset
 
         # Now strip off the leading path, so each file becomes relative, and remove
         # any slashes that might end up at the beginning of the path.
-        result = files.collect { |file| file.sub(%r{^#{Regexp.escape(@path)}/*}, '') }
+        result = files.collect { |file| file.sub(%r{^#{@path}/*}, '') }
 
         # And add the path itself.
         result.unshift(".")
@@ -120,7 +120,7 @@ class Puppet::FileServing::Fileset
 
         return result
     end
-    public
+
     # Stat a given file, using the links-appropriate method.
     def stat(path)
         unless defined?(@stat_method)
diff --git a/lib/puppet/file_serving/metadata.rb b/lib/puppet/file_serving/metadata.rb
index b277955..beecaef 100644
--- a/lib/puppet/file_serving/metadata.rb
+++ b/lib/puppet/file_serving/metadata.rb
@@ -60,10 +60,10 @@ class Puppet::FileServing::Metadata < Puppet::FileServing::FileBase
 
         case stat.ftype
         when "file":
-            @checksum = ("{%s}" % @checksum_type) + send("%s_file" % @checksum_type, real_path).to_s
+            @checksum = ("{%s}" % @checksum_type) + send("%s_file" % @checksum_type, real_path)
         when "directory": # Always just timestamp the directory.
-            @checksum_type = "ctime"
-            @checksum = ("{%s}" % @checksum_type) + send("%s_file" % @checksum_type, path).to_s
+            sumtype = @checksum_type.to_s =~ /time/ ? @checksum_type : "ctime"
+            @checksum = ("{%s}" % sumtype) + send("%s_file" % sumtype, path).to_s
         when "link":
             @destination = File.readlink(real_path)
         else
diff --git a/lib/puppet/file_serving/terminus_helper.rb b/lib/puppet/file_serving/terminus_helper.rb
index e5da0e2..d465aa4 100644
--- a/lib/puppet/file_serving/terminus_helper.rb
+++ b/lib/puppet/file_serving/terminus_helper.rb
@@ -8,11 +8,11 @@ require 'puppet/file_serving/fileset'
 # Define some common methods for FileServing termini.
 module Puppet::FileServing::TerminusHelper
     # Create model instances for all files in a fileset.
-    def path2instances(request, path)
-        args = [:links, :ignore, :recurse].inject({}) { |hash, param| hash[param] = request.options[param] if request.options[param]; hash }
+    def path2instances(key, path, options = {})
+        args = [:links, :ignore, :recurse].inject({}) { |hash, param| hash[param] = options[param] if options[param]; hash }
         Puppet::FileServing::Fileset.new(path, args).files.collect do |file|
-            inst = model.new(File.join(request.key, file), :path => path, :relative_path => file)
-            inst.links = request.options[:links] if request.options[:links]
+            inst = model.new(File.join(key, file), :path => path, :relative_path => file)
+            inst.links = options[:links] if options[:links]
             inst
         end
     end
diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb
index a6a8128..2b5e8d9 100644
--- a/lib/puppet/indirector/catalog/compiler.rb
+++ b/lib/puppet/indirector/catalog/compiler.rb
@@ -14,7 +14,7 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code
 
     # Compile a node's catalog.
     def find(request)
-        unless node = request.options[:use_node] || find_node(request.key)
+        unless node = request.options[:node] || find_node(request.key)
             raise ArgumentError, "Could not find node '%s'; cannot compile" % request.key
         end
 
@@ -89,7 +89,7 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code
         #    key = client
         #end
 
-        return nil unless node = Puppet::Node.find(key)
+        return nil unless node = Puppet::Node.find_by_any_name(key)
 
         # Add any external data to the node.
         add_node_data(node)
diff --git a/lib/puppet/indirector/direct_file_server.rb b/lib/puppet/indirector/direct_file_server.rb
index b3b4886..1711356 100644
--- a/lib/puppet/indirector/direct_file_server.rb
+++ b/lib/puppet/indirector/direct_file_server.rb
@@ -22,6 +22,6 @@ class Puppet::Indirector::DirectFileServer < Puppet::Indirector::Terminus
     def search(request)
         uri = key2uri(request.key)
         return nil unless FileTest.exists?(uri.path)
-        path2instances(request, uri.path)
+        path2instances(request.key, uri.path, request.options)
     end
 end
diff --git a/lib/puppet/indirector/facts/facter.rb b/lib/puppet/indirector/facts/facter.rb
index 6ed89da..465d90c 100644
--- a/lib/puppet/indirector/facts/facter.rb
+++ b/lib/puppet/indirector/facts/facter.rb
@@ -12,13 +12,12 @@ class Puppet::Node::Facts::Facter < Puppet::Indirector::Code
         Dir.entries(dir).find_all { |e| e =~ /\.rb$/ }.each do |file|
             fqfile = ::File.join(dir, file)
             begin
-                Puppet.info "Loading %s %s" % 
-                    [type, ::File.basename(file.sub(".rb",''))]
+                Puppet.info "Loading #{type} %s" % ::File.basename(file.sub(".rb",''))
                 Timeout::timeout(self.timeout) do
                     load fqfile
                 end
             rescue => detail
-                Puppet.warning "Could not load %s %s: %s" % [type, fqfile, detail]
+                Puppet.warning "Could not load #{type} %s: %s" % [fqfile, detail]
             end
         end
     end
diff --git a/lib/puppet/indirector/file_server.rb b/lib/puppet/indirector/file_server.rb
index b0df7ff..2eb323d 100644
--- a/lib/puppet/indirector/file_server.rb
+++ b/lib/puppet/indirector/file_server.rb
@@ -14,28 +14,28 @@ class Puppet::Indirector::FileServer < Puppet::Indirector::Terminus
     include Puppet::FileServing::TerminusHelper
 
     # Is the client authorized to perform this action?
-    def authorized?(request)
-        return false unless [:find, :search].include?(request.method)
+    def authorized?(method, key, options = {})
+        return false unless [:find, :search].include?(method)
 
-        uri = key2uri(request.key)
+        uri = key2uri(key)
 
-        configuration.authorized?(uri.path, :node => request.node, :ipaddress => request.ip)
+        configuration.authorized?(uri.path, :node => options[:node], :ipaddress => options[:ipaddress])
     end
 
     # Find our key using the fileserver.
-    def find(request)
-        return nil unless path = find_path(request)
-        result =  model.new(request.key, :path => path)
-        result.links = request.options[:links] if request.options[:links]
+    def find(key, options = {})
+        return nil unless path = find_path(key, options)
+        result =  model.new(key, :path => path)
+        result.links = options[:links] if options[:links]
         return result
     end
 
     # Search for files.  This returns an array rather than a single
     # file.
-    def search(request)
-        return nil unless path = find_path(request)
+    def search(key, options = {})
+        return nil unless path = find_path(key, options)
 
-        path2instances(request, path)
+        path2instances(key, path, options)
     end
 
     private
@@ -46,10 +46,10 @@ class Puppet::Indirector::FileServer < Puppet::Indirector::Terminus
     end
 
     # Find our path; used by :find and :search.
-    def find_path(request)
-        uri = key2uri(request.key)
+    def find_path(key, options)
+        uri = key2uri(key)
 
-        return nil unless path = configuration.file_path(uri.path, :node => request.node)
+        return nil unless path = configuration.file_path(uri.path, :node => options[:node])
 
         return path
     end
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb
index 4841ec5..05464f8 100644
--- a/lib/puppet/indirector/indirection.rb
+++ b/lib/puppet/indirector/indirection.rb
@@ -267,7 +267,7 @@ class Puppet::Indirector::Indirection
     def check_authorization(request, terminus)
         # At this point, we're assuming authorization makes no sense without
         # client information.
-        return unless request.node
+        return unless request.options[:node]
 
         # This is only to authorize via a terminus-specific authorization hook.
         return unless terminus.respond_to?(:authorized?)
diff --git a/lib/puppet/indirector/ldap.rb b/lib/puppet/indirector/ldap.rb
index 7485bd9..07ad389 100644
--- a/lib/puppet/indirector/ldap.rb
+++ b/lib/puppet/indirector/ldap.rb
@@ -1,15 +1,19 @@
 require 'puppet/indirector/terminus'
-require 'puppet/util/ldap/connection'
 
 class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus
     # Perform our ldap search and process the result.
     def find(request)
-        return ldapsearch(search_filter(request.key)) { |entry| return process(entry) } || nil
+        # We have to use 'yield' here because the LDAP::Entry objects
+        # get destroyed outside the scope of the search, strangely.
+        ldapsearch(request.key) { |entry| return process(request.key, entry) }
+
+        # Return nil if we haven't found something.
+        return nil
     end
 
     # Process the found entry.  We assume that we don't just want the
     # ldap object.
-    def process(entry)
+    def process(name, entry)
         raise Puppet::DevError, "The 'process' method has not been overridden for the LDAP terminus for %s" % self.name
     end
 
@@ -29,14 +33,14 @@ class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus
 
     # Find the ldap node, return the class list and parent node specially,
     # and everything else in a parameter hash.
-    def ldapsearch(filter)
+    def ldapsearch(node)
         raise ArgumentError.new("You must pass a block to ldapsearch") unless block_given?
 
         found = false
         count = 0
 
         begin
-            connection.search(search_base, 2, filter, search_attributes) do |entry|
+            connection.search(search_base, 2, search_filter(node), search_attributes) do |entry|
                 found = true
                 yield entry
             end
@@ -48,15 +52,15 @@ class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus
                 Puppet.warning "Retrying LDAP connection"
                 retry
             else
-                error = Puppet::Error.new("LDAP Search failed")
-                error.set_backtrace(detail.backtrace)
-                raise error
+                raise Puppet::Error, "LDAP Search failed: %s" % detail
             end
         end
 
         return found
     end
 
+    private
+
     # Create an ldap connection.
     def connection
         unless defined? @connection and @connection
@@ -64,11 +68,19 @@ class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus
                 raise Puppet::Error, "Could not set up LDAP Connection: Missing ruby/ldap libraries"
             end
             begin
-                conn = Puppet::Util::Ldap::Connection.instance
-                conn.start
-                @connection = conn.connection
+                if Puppet[:ldapssl]
+                    @connection = LDAP::SSLConn.new(Puppet[:ldapserver], Puppet[:ldapport])
+                elsif Puppet[:ldaptls]
+                    @connection = LDAP::SSLConn.new(
+                        Puppet[:ldapserver], Puppet[:ldapport], true
+                    )
+                else
+                    @connection = LDAP::Conn.new(Puppet[:ldapserver], Puppet[:ldapport])
+                end
+                @connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
+                @connection.set_option(LDAP::LDAP_OPT_REFERRALS, LDAP::LDAP_OPT_ON)
+                @connection.simple_bind(Puppet[:ldapuser], Puppet[:ldappassword])
             rescue => detail
-                puts detail.backtrace if Puppet[:trace]
                 raise Puppet::Error, "Could not connect to LDAP: %s" % detail
             end
         end
diff --git a/lib/puppet/indirector/module_files.rb b/lib/puppet/indirector/module_files.rb
index cf5c29c..84286d8 100644
--- a/lib/puppet/indirector/module_files.rb
+++ b/lib/puppet/indirector/module_files.rb
@@ -14,24 +14,24 @@ class Puppet::Indirector::ModuleFiles < Puppet::Indirector::Terminus
     include Puppet::FileServing::TerminusHelper
 
     # Is the client allowed access to this key with this method?
-    def authorized?(request)
-        return false unless [:find, :search].include?(request.method)
+    def authorized?(method, key, options = {})
+        return false unless [:find, :search].include?(method)
 
-        uri = key2uri(request.key)
+        uri = key2uri(key)
 
         # Make sure our file path starts with /modules, so that we authorize
         # against the 'modules' mount.
         path = uri.path =~ /^\/modules/ ? uri.path : "/modules" + uri.path
 
-        configuration.authorized?(path, :node => request.node, :ipaddress => request.ip)
+        configuration.authorized?(path, :node => options[:node], :ipaddress => options[:ipaddress])
     end
 
     # Find our key in a module.
-    def find(request)
-        return nil unless path = find_path(request)
+    def find(key, options = {})
+        return nil unless path = find_path(key, options)
 
-        result = model.new(request.key, :path => path)
-        result.links = request.options[:links] if request.options[:links]
+        result = model.new(key, :path => path)
+        result.links = options[:links] if options[:links]
         return result
     end
 
@@ -41,9 +41,9 @@ class Puppet::Indirector::ModuleFiles < Puppet::Indirector::Terminus
     end
 
     # Search for a list of files.
-    def search(request)
-        return nil unless path = find_path(request)
-        path2instances(request, path)
+    def search(key, options = {})
+        return nil unless path = find_path(key, options)
+        path2instances(key, path, options)
     end
 
     private
@@ -63,15 +63,15 @@ class Puppet::Indirector::ModuleFiles < Puppet::Indirector::Terminus
     end
 
     # The abstracted method for turning a key into a path; used by both :find and :search.
-    def find_path(request)
-        uri = key2uri(request.key)
+    def find_path(key, options)
+        uri = key2uri(key)
 
         # Strip off /modules if it's there -- that's how requests get routed to this terminus.
         # Also, strip off the leading slash if present.
         module_name, relative_path = uri.path.sub(/^\/modules\b/, '').sub(%r{^/}, '').split(File::Separator, 2)
 
         # And use the environment to look up the module.
-        return nil unless mod = find_module(module_name, request.node)
+        return nil unless mod = find_module(module_name, options[:node])
 
         path = File.join(mod.files, relative_path)
 
diff --git a/lib/puppet/indirector/node/ldap.rb b/lib/puppet/indirector/node/ldap.rb
index 01010a2..6c41c18 100644
--- a/lib/puppet/indirector/node/ldap.rb
+++ b/lib/puppet/indirector/node/ldap.rb
@@ -3,9 +3,7 @@ require 'puppet/indirector/ldap'
 
 class Puppet::Node::Ldap < Puppet::Indirector::Ldap
     desc "Search in LDAP for node configuration information.  See
-    the `LdapNodes`:trac: page for more information.  This will first
-    search for whatever the certificate name is, then (if that name
-    contains a '.') for the short name, then 'default'."
+    the `LdapNodes`:trac: page for more information."
 
     # The attributes that Puppet class information is stored in.
     def class_attributes
@@ -13,53 +11,46 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
         x = Puppet[:ldapclassattrs].split(/\s*,\s*/)
     end
 
-    # Separate this out so it's relatively atomic.  It's tempting to call
-    # process() instead of name2hash() here, but it ends up being
-    # difficult to test because all exceptions get caught by ldapsearch.
-    # LAK:NOTE Unfortunately, the ldap support is too stupid to throw anything
-    # but LDAP::ResultError, even on bad connections, so we are rough handed
-    # with our error handling.
-    def name2hash(name)
-        info = nil
-        ldapsearch(search_filter(name)) { |entry| info = entry2hash(entry) }
-        return info
-    end
-
     # Look for our node in ldap.
     def find(request)
-        names = [request.key]
-        if request.key.include?(".") # we assume it's an fqdn
-            names << request.key.sub(/\..+/, '')
-        end
-        names << "default"
+        return nil unless information = super
 
-        node = nil
-        names.each do |name|
-            next unless info = name2hash(name)
+        name = request.key
 
-            break if node = info2node(request.key, info)
-        end
+        node = Puppet::Node.new(name)
 
-        return node
-    end
+        parent_info = nil
+        parent = information[:parent]
+        parents = [name]
+        while parent
+            if parents.include?(parent)
+                raise ArgumentError, "Found loop in LDAP node parents; %s appears twice" % parent
+            end
+            parents << parent
 
-    # Find more than one node.  LAK:NOTE This is a bit of a clumsy API, because the 'search'
-    # method currently *requires* a key.  It seems appropriate in some cases but not others,
-    # and I don't really know how to get rid of it as a requirement but allow it when desired.
-    def search(request)
-        if classes = request.options[:class]
-            classes = [classes] unless classes.is_a?(Array)
-            filter = "(&(objectclass=puppetClient)(puppetclass=" + classes.join(")(puppetclass=") + "))"
-        else
-            filter = "(objectclass=puppetClient)"
-        end
+            ldapsearch(parent) { |entry| parent_info = process(parent, entry) }
 
-        infos = []
-        ldapsearch(filter) { |entry| infos << entry2hash(entry) }
+            unless parent_info
+                raise Puppet::Error.new("Could not find parent node '%s'" % parent)
+            end
+            information[:classes] += parent_info[:classes]
+            parent_info[:parameters].each do |param, value|
+                # Specifically test for whether it's set, so false values are handled
+                # correctly.
+                information[:parameters][param] = value unless information[:parameters].include?(param)
+            end
 
-        return infos.collect do |info|
-            info2node(info[:name], info)
+            information[:environment] ||= parent_info[:environment]
+
+            parent = parent_info[:parent]
         end
+
+        node.classes = information[:classes].uniq unless information[:classes].empty?
+        node.parameters = information[:parameters] unless information[:parameters].empty?
+        node.environment = information[:environment] if information[:environment]
+        node.fact_merge
+
+        return node
     end
 
     # The parent attribute, if we have one.
@@ -71,21 +62,15 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
         end
     end
 
-    # The attributes that Puppet will stack as array over the full
-    # hierarchy.
-    def stacked_attributes
-        Puppet[:ldapstackedattrs].split(/\s*,\s*/)
-    end
-
-    # Convert the found entry into a simple hash.
-    def entry2hash(entry)
+    # Process the found entry.  We assume that we don't just want the
+    # ldap object.
+    def process(name, entry)
         result = {}
-        result[:name] = entry.dn.split(',')[0].split("=")[1]
         if pattr = parent_attribute
             if values = entry.vals(pattr)
                 if values.length > 1
                     raise Puppet::Error,
-                        "Node entry %s specifies more than one parent: %s" % [entry.dn, values.inspect]
+                        "Node %s has more than one parent: %s" % [name, values.inspect]
                 end
                 unless values.empty?
                     result[:parent] = values.shift
@@ -99,46 +84,19 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
                 values.each do |v| result[:classes] << v end
             end
         }
-        result[:classes].uniq!
-
-        result[:stacked] = []
-        stacked_params = stacked_attributes
-        stacked_params.each { |attr|
-            if values = entry.vals(attr)
-                result[:stacked] = result[:stacked] + values
-            end
-        }
-        
 
         result[:parameters] = entry.to_hash.inject({}) do |hash, ary|
-            unless stacked_params.include?(ary[0]) # don't add our stacked parameters to the main param list
-                if ary[1].length == 1
-                    hash[ary[0]] = ary[1].shift
-                else
-                    hash[ary[0]] = ary[1]
-                end
+            if ary[1].length == 1
+                hash[ary[0]] = ary[1].shift
+            else
+                hash[ary[0]] = ary[1]
             end
             hash
         end
 
         result[:environment] = result[:parameters]["environment"] if result[:parameters]["environment"]
 
-        result[:stacked_parameters] = {}
-
-        if result[:stacked]
-            result[:stacked].each do |value|
-                param = value.split('=', 2)
-                result[:stacked_parameters][param[0]] = param[1]
-            end
-        end
-
-        if result[:stacked_parameters]
-            result[:stacked_parameters].each do |param, value|
-                result[:parameters][param] = value unless result[:parameters].include?(param)
-            end
-        end
-
-        result
+        return result
     end
 
     # Default to all attributes.
@@ -168,60 +126,4 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
         end
         filter
     end
-
-    private
-
-    # Add our hash of ldap information to the node instance.
-    def add_to_node(node, information)
-        node.classes = information[:classes].uniq unless information[:classes].nil? or information[:classes].empty?
-        node.parameters = information[:parameters] unless information[:parameters].nil? or information[:parameters].empty?
-        node.environment = information[:environment] if information[:environment]
-    end
-
-    # Find information for our parent and merge it into the current info.
-    def find_and_merge_parent(parent, information)
-        unless parent_info = name2hash(parent)
-            raise Puppet::Error.new("Could not find parent node '%s'" % parent)
-        end
-        information[:classes] += parent_info[:classes]
-        parent_info[:parameters].each do |param, value|
-            # Specifically test for whether it's set, so false values are handled
-            # correctly.
-            information[:parameters][param] = value unless information[:parameters].include?(param)
-        end
-
-        information[:environment] ||= parent_info[:environment]
-
-        parent_info[:parent]
-    end
-
-    # Take a name and a hash, and return a node instance.
-    def info2node(name, info)
-        merge_parent(info) if info[:parent]
-
-        node = Puppet::Node.new(name)
-
-        add_to_node(node, info)
-
-        node.fact_merge
-
-        node
-    end
-
-    def merge_parent(info)
-        parent_info = nil
-        parent = info[:parent]
-
-        # Preload the parent array with the node name.
-        parents = [info[:name]]
-        while parent
-            if parents.include?(parent)
-                raise ArgumentError, "Found loop in LDAP node parents; %s appears twice" % parent
-            end
-            parents << parent
-            parent = find_and_merge_parent(parent, info)
-        end
-
-        return info
-    end
 end
diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb
index 98fa388..68b7ee1 100644
--- a/lib/puppet/indirector/request.rb
+++ b/lib/puppet/indirector/request.rb
@@ -3,29 +3,10 @@ require 'puppet/indirector'
 # Provide any attributes or functionality needed for indirected
 # instances.
 class Puppet::Indirector::Request
-    attr_accessor :indirection_name, :key, :method, :options, :instance, :node, :ip, :authenticated
-
-    # Is this an authenticated request?
-    def authenticated?
-        # Double negative, so we just get true or false
-        ! ! authenticated
-    end
+    attr_accessor :indirection_name, :key, :method, :options, :instance
 
     def initialize(indirection_name, method, key, options = {})
-        options ||= {}
-        raise ArgumentError, "Request options must be a hash, not %s" % options.class unless options.is_a?(Hash)
-
-        @indirection_name, @method = indirection_name, method
-
-        @options = options.inject({}) do |result, ary|
-            param, value = ary
-            if respond_to?(param.to_s + "=")
-                send(param.to_s + "=", value)
-            else
-                result[param] = value
-            end
-            result
-        end
+        @indirection_name, @method, @options = indirection_name, method, (options || {})
 
         if key.is_a?(String) or key.is_a?(Symbol)
             @key = key
@@ -33,6 +14,8 @@ class Puppet::Indirector::Request
             @instance = key
             @key = @instance.name
         end
+
+        raise ArgumentError, "Request options must be a hash, not %s" % @options.class unless @options.is_a?(Hash)
     end
 
     # Look up the indirection based on the name provided.
diff --git a/lib/puppet/indirector/yaml.rb b/lib/puppet/indirector/yaml.rb
index 3f05ce6..23bca02 100644
--- a/lib/puppet/indirector/yaml.rb
+++ b/lib/puppet/indirector/yaml.rb
@@ -34,19 +34,9 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
         end
     end
 
-    # Get the yaml directory
-    def base
-      (Puppet[:name] == "puppetmasterd") ? Puppet[:yamldir] : Puppet[:clientyamldir]
-    end
-
     # Return the path to a given node's file.
     def path(name)
-        File.join(base, self.class.indirection_name.to_s, name.to_s + ".yaml")
-    end
-    
-    # Do a glob on the yaml directory, loading each file found
-    def search(request)
-      Dir.glob(File.join(base, self.class.indirection_name.to_s, request.key)).collect { |f| YAML.load_file(f) }
+        File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml")
     end
 
     private
diff --git a/lib/puppet/metatype/attributes.rb b/lib/puppet/metatype/attributes.rb
new file mode 100644
index 0000000..3f48f22
--- /dev/null
+++ b/lib/puppet/metatype/attributes.rb
@@ -0,0 +1,685 @@
+require 'puppet'
+require 'puppet/type'
+
+class Puppet::Type
+    class << self
+        include Puppet::Util::ClassGen
+        include Puppet::Util::Warnings
+        attr_reader :properties
+    end
+
+    def self.states
+        warnonce "The states method is deprecated; use properties"
+        properties()
+    end
+
+    # All parameters, in the appropriate order.  The namevar comes first,
+    # then the properties, then the params and metaparams in the order they
+    # were specified in the files.
+    def self.allattrs
+        # now get all of the arguments, in a specific order
+        # Cache this, since it gets called so many times
+        namevar = self.namevar
+
+        order = [namevar]
+        if self.parameters.include?(:provider)
+            order << :provider
+        end
+        order << [self.properties.collect { |property| property.name },
+            self.parameters - [:provider],
+            self.metaparams].flatten.reject { |param|
+                # we don't want our namevar in there multiple times
+                param == namevar
+        }
+
+        order.flatten!
+
+        return order
+    end
+
+    # Retrieve an attribute alias, if there is one.
+    def self.attr_alias(param)
+        @attr_aliases[symbolize(param)]
+    end
+
+    # Create an alias to an existing attribute.  This will cause the aliased
+    # attribute to be valid when setting and retrieving values on the instance.
+    def self.set_attr_alias(hash)
+        hash.each do |new, old|
+            @attr_aliases[symbolize(new)] = symbolize(old)
+        end
+    end
+
+    # Find the class associated with any given attribute.
+    def self.attrclass(name)
+        @attrclasses ||= {}
+
+        # We cache the value, since this method gets called such a huge number
+        # of times (as in, hundreds of thousands in a given run).
+        unless @attrclasses.include?(name)
+            @attrclasses[name] = case self.attrtype(name)
+            when :property: @validproperties[name]
+            when :meta: @@metaparamhash[name]
+            when :param: @paramhash[name]
+            end
+        end
+        @attrclasses[name]
+    end
+
+    # What type of parameter are we dealing with? Cache the results, because
+    # this method gets called so many times.
+    def self.attrtype(attr)
+        @attrtypes ||= {}
+        unless @attrtypes.include?(attr)
+            @attrtypes[attr] = case
+                when @validproperties.include?(attr): :property
+                when @paramhash.include?(attr): :param
+                when @@metaparamhash.include?(attr): :meta
+                else
+                    raise Puppet::DevError,
+                        "Invalid attribute '%s' for class '%s'" %
+                        [attr, self.name]
+                end
+        end
+
+        @attrtypes[attr]
+    end
+
+    # Copy an existing class parameter.  This allows other types to avoid
+    # duplicating a parameter definition, and is mostly used by subclasses
+    # of the File class.
+    def self.copyparam(klass, name)
+        param = klass.attrclass(name)
+
+        unless param
+            raise Puppet::DevError, "Class %s has no param %s" % [klass, name]
+        end
+        @parameters << param
+        @parameters.each { |p| @paramhash[name] = p }
+
+        if param.isnamevar?
+            @namevar = param.name
+        end
+    end
+
+    # A similar function but one that yields the class and type.
+    # This is mainly so that setdefaults doesn't call quite so many functions.
+    def self.eachattr(*ary)
+        if ary.empty?
+            ary = nil
+        end
+
+        # We have to do this in a specific order, so that defaults are
+        # created in that order (e.g., providers should be set up before
+        # anything else).
+        allattrs.each do |name|
+            next unless ary.nil? or ary.include?(name)
+            if obj = @properties.find { |p| p.name == name }
+                yield obj, :property
+            elsif obj = @parameters.find { |p| p.name == name }
+                yield obj, :param
+            elsif obj = @@metaparams.find { |p| p.name == name }
+                yield obj, :meta
+            else
+                raise Puppet::DevError, "Could not find parameter %s" % name
+            end
+        end
+    end
+
+    def self.eachmetaparam
+        @@metaparams.each { |p| yield p.name }
+    end
+
+    # Create the 'ensure' class.  This is a separate method so other types
+    # can easily call it and create their own 'ensure' values.
+    def self.ensurable(&block)
+        if block_given?
+            self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block)
+        else
+            self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do
+                self.defaultvalues
+            end
+        end
+    end
+
+    # Should we add the 'ensure' property to this class?
+    def self.ensurable?
+        # If the class has all three of these methods defined, then it's
+        # ensurable.
+        ens = [:exists?, :create, :destroy].inject { |set, method|
+            set &&= self.public_method_defined?(method)
+        }
+
+        return ens
+    end
+    
+    # Deal with any options passed into parameters.
+    def self.handle_param_options(name, options)
+        # If it's a boolean parameter, create a method to test the value easily
+        if options[:boolean]
+            define_method(name.to_s + "?") do
+                val = self[name]
+                if val == :true or val == true
+                    return true
+                end
+            end
+        end
+        
+        # If this param handles relationships, store that information
+    end
+
+    # Is the parameter in question a meta-parameter?
+    def self.metaparam?(param)
+        @@metaparamhash.include?(symbolize(param))
+    end
+
+    # Find the metaparameter class associated with a given metaparameter name.
+    def self.metaparamclass(name)
+        @@metaparamhash[symbolize(name)]
+    end
+
+    def self.metaparams
+        @@metaparams.collect { |param| param.name }
+    end
+
+    def self.metaparamdoc(metaparam)
+        @@metaparamhash[metaparam].doc
+    end
+
+    # Create a new metaparam.  Requires a block and a name, stores it in the
+    # @parameters array, and does some basic checking on it.
+    def self.newmetaparam(name, options = {}, &block)
+        @@metaparams ||= []
+        @@metaparamhash ||= {}
+        name = symbolize(name)
+
+        param = genclass(name,
+            :parent => options[:parent] || Puppet::Parameter,
+            :prefix => "MetaParam",
+            :hash => @@metaparamhash,
+            :array => @@metaparams,
+            :attributes => options[:attributes],
+            &block
+        )
+
+        # Grr.
+        if options[:required_features]
+            param.required_features = options[:required_features]
+        end
+        
+        handle_param_options(name, options)
+
+        param.metaparam = true
+
+        return param
+    end
+
+    # Find the namevar
+    def self.namevar
+        unless defined? @namevar
+            params = @parameters.find_all { |param|
+                param.isnamevar? or param.name == :name
+            }
+
+            if params.length > 1
+                raise Puppet::DevError, "Found multiple namevars for %s" % self.name
+            elsif params.length == 1
+                @namevar = params[0].name
+            else
+                raise Puppet::DevError, "No namevar for %s" % self.name
+            end
+        end
+        @namevar
+    end
+
+    # Create a new parameter.  Requires a block and a name, stores it in the
+    # @parameters array, and does some basic checking on it.
+    def self.newparam(name, options = {}, &block)
+        options[:attributes] ||= {}
+        param = genclass(name,
+            :parent => options[:parent] || Puppet::Parameter,
+            :attributes => options[:attributes],
+            :block => block,
+            :prefix => "Parameter",
+            :array => @parameters,
+            :hash => @paramhash
+        )
+        
+        handle_param_options(name, options)
+
+        # Grr.
+        if options[:required_features]
+            param.required_features = options[:required_features]
+        end
+
+        param.isnamevar if options[:namevar]
+
+        # These might be enabled later.
+#        define_method(name) do
+#            @parameters[name].value
+#        end
+#
+#        define_method(name.to_s + "=") do |value|
+#            newparam(param, value)
+#        end
+
+        if param.isnamevar?
+            @namevar = param.name
+        end
+
+        return param
+    end
+
+    def self.newstate(name, options = {}, &block)
+        Puppet.warning "newstate() has been deprecrated; use newproperty(%s)" %
+            name
+        newproperty(name, options, &block)
+    end
+
+    # Create a new property. The first parameter must be the name of the property;
+    # this is how users will refer to the property when creating new instances.
+    # The second parameter is a hash of options; the options are:
+    # * <tt>:parent</tt>: The parent class for the property.  Defaults to Puppet::Property.
+    # * <tt>:retrieve</tt>: The method to call on the provider or @parent object (if
+    #   the provider is not set) to retrieve the current value.
+    def self.newproperty(name, options = {}, &block)
+        name = symbolize(name)
+
+        # This is here for types that might still have the old method of defining
+        # a parent class.
+        unless options.is_a? Hash
+            raise Puppet::DevError,
+                "Options must be a hash, not %s" % options.inspect
+        end
+
+        if @validproperties.include?(name) 
+            raise Puppet::DevError, "Class %s already has a property named %s" %
+                [self.name, name]
+        end
+
+        if parent = options[:parent]
+            options.delete(:parent)
+        else
+            parent = Puppet::Property
+        end
+
+        # We have to create our own, new block here because we want to define
+        # an initial :retrieve method, if told to, and then eval the passed
+        # block if available.
+        prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do
+            # If they've passed a retrieve method, then override the retrieve
+            # method on the class.
+            if options[:retrieve]
+                define_method(:retrieve) do
+                    provider.send(options[:retrieve])
+                end
+            end
+
+            if block
+                class_eval(&block)
+            end
+        end
+
+        # If it's the 'ensure' property, always put it first.
+        if name == :ensure
+            @properties.unshift prop
+        else
+            @properties << prop
+        end
+
+#        define_method(name) do
+#            @parameters[name].should
+#        end
+#
+#        define_method(name.to_s + "=") do |value|
+#            newproperty(name, :should => value)
+#        end
+
+        return prop
+    end
+
+    def self.paramdoc(param)
+        @paramhash[param].doc
+    end
+
+    # Return the parameter names
+    def self.parameters
+        return [] unless defined? @parameters
+        @parameters.collect { |klass| klass.name }
+    end
+
+    # Find the parameter class associated with a given parameter name.
+    def self.paramclass(name)
+        @paramhash[name]
+    end
+
+    # Return the property class associated with a name
+    def self.propertybyname(name)
+        @validproperties[name]
+    end
+
+    def self.validattr?(name)
+        name = symbolize(name)
+        return true if name == :name
+        @validattrs ||= {}
+
+        unless @validattrs.include?(name)
+            if self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)
+                @validattrs[name] = true
+            else
+                @validattrs[name] = false
+            end
+        end
+
+        @validattrs[name]
+    end
+
+    # does the name reflect a valid property?
+    def self.validproperty?(name)
+        name = symbolize(name)
+        if @validproperties.include?(name)
+            return @validproperties[name]
+        else
+            return false
+        end
+    end
+
+    # Return the list of validproperties
+    def self.validproperties
+        return {} unless defined? @parameters
+
+        return @validproperties.keys
+    end
+
+    # does the name reflect a valid parameter?
+    def self.validparameter?(name)
+        unless defined? @parameters
+            raise Puppet::DevError, "Class %s has not defined parameters" % self
+        end
+        if @paramhash.include?(name) or @@metaparamhash.include?(name)
+            return true
+        else
+            return false
+        end
+    end
+
+    # fix any namevar => param translations
+    def argclean(oldhash)
+        # This duplication is here because it might be a transobject.
+        hash = oldhash.dup.to_hash
+
+        if hash.include?(:resource)
+            hash.delete(:resource)
+        end
+        namevar = self.class.namevar
+
+        # Do a simple translation for those cases where they've passed :name
+        # but that's not our namevar
+        if hash.include? :name and namevar != :name
+            if hash.include? namevar
+                raise ArgumentError, "Cannot provide both name and %s" % namevar
+            end
+            hash[namevar] = hash[:name]
+            hash.delete(:name)
+        end
+
+        # Make sure we have a name, one way or another
+        unless hash.include? namevar
+            if defined? @title and @title
+                hash[namevar] = @title
+            else
+                raise Puppet::Error, "Was not passed a namevar or title"
+            end
+        end
+
+        return hash
+    end
+
+    # Return either the attribute alias or the attribute.
+    def attr_alias(name)
+        name = symbolize(name)
+        if synonym = self.class.attr_alias(name)
+            return synonym
+        else
+            return name
+        end
+    end
+    
+    # Are we deleting this resource?
+    def deleting?
+        obj = @parameters[:ensure] and obj.should == :absent
+    end
+
+    # Create a new property if it is valid but doesn't exist
+    # Returns: true if a new parameter was added, false otherwise
+    def add_property_parameter(prop_name)
+        if self.class.validproperty?(prop_name) && !@parameters[prop_name]
+            self.newattr(prop_name)
+            return true
+        end
+        return false
+    end
+    
+    # abstract accessing parameters and properties, and normalize
+    # access to always be symbols, not strings
+    # This returns a value, not an object.  It returns the 'is'
+    # value, but you can also specifically return 'is' and 'should'
+    # values using 'object.is(:property)' or 'object.should(:property)'.
+    def [](name)
+        name = attr_alias(name)
+
+        unless self.class.validattr?(name)
+            raise TypeError.new("Invalid parameter %s(%s)" % [name, name.inspect])
+        end
+
+        if name == :name
+            name = self.class.namevar
+        end
+
+        if obj = @parameters[name]
+            # Note that if this is a property, then the value is the "should" value,
+            # not the current value.
+            obj.value
+        else
+            return nil
+        end
+    end
+
+    # Abstract setting parameters and properties, and normalize
+    # access to always be symbols, not strings.  This sets the 'should'
+    # value on properties, and otherwise just sets the appropriate parameter.
+    def []=(name,value)
+        name = attr_alias(name)
+
+        unless self.class.validattr?(name)
+            raise TypeError.new("Invalid parameter %s" % [name])
+        end
+
+        if name == :name
+            name = self.class.namevar
+        end
+        if value.nil?
+            raise Puppet::Error.new("Got nil value for %s" % name)
+        end
+
+        if obj = @parameters[name]
+            obj.value = value
+            return nil
+        else
+            self.newattr(name, :value => value)
+        end
+
+        nil
+    end
+
+    # remove a property from the object; useful in testing or in cleanup
+    # when an error has been encountered
+    def delete(attr)
+        attr = symbolize(attr)
+        if @parameters.has_key?(attr)
+            @parameters.delete(attr)
+        else
+            raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}")
+        end
+    end
+
+    # iterate across the existing properties
+    def eachproperty
+        # properties() is a private method
+        properties().each { |property|
+            yield property
+        }
+    end
+
+    # retrieve the 'should' value for a specified property
+    def should(name)
+        name = attr_alias(name)
+        if prop = @parameters[name] and prop.is_a?(Puppet::Property)
+            return prop.should
+        else
+            return nil
+        end
+    end
+
+    # Create the actual attribute instance.  Requires either the attribute
+    # name or class as the first argument, then an optional hash of
+    # attributes to set during initialization.
+    def newattr(name, options = {})
+        if name.is_a?(Class)
+            klass = name
+            name = klass.name
+        end
+
+        unless klass = self.class.attrclass(name)
+            raise Puppet::Error, "Resource type %s does not support parameter %s" % [self.class.name, name]
+        end
+
+        if @parameters.include?(name)
+            raise Puppet::Error, "Parameter '%s' is already defined in %s" %
+                [name, self.ref]
+        end
+
+        if provider and ! provider.class.supports_parameter?(klass)
+            missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) }
+            info "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name]
+            return nil
+        end
+
+        # Add resource information at creation time, so it's available
+        # during validation.
+        options[:resource] = self
+        begin
+            # make sure the parameter doesn't have any errors
+            return @parameters[name] = klass.new(options)
+        rescue => detail
+            error = Puppet::Error.new("Parameter %s failed: %s" %
+                [name, detail])
+            error.set_backtrace(detail.backtrace)
+            raise error
+        end
+    end
+
+    # return the value of a parameter
+    def parameter(name)
+        unless name.is_a? Symbol
+            name = name.intern
+        end
+        return @parameters[name].value
+    end
+
+    # Is the named property defined?
+    def propertydefined?(name)
+        unless name.is_a? Symbol
+            name = name.intern
+        end
+        return @parameters.include?(name)
+    end
+
+    # return an actual type by name; to return the value, use 'inst[name]'
+    # FIXME this method should go away
+    def property(name)
+        if obj = @parameters[symbolize(name)] and obj.is_a?(Puppet::Property)
+            return obj
+        else
+            return nil
+        end
+    end
+
+#    def set(name, value)
+#        send(name.to_s + "=", value)
+#    end
+#
+#    def get(name)
+#        send(name)
+#    end
+
+    # For any parameters or properties that have defaults and have not yet been
+    # set, set them now.  This method can be handed a list of attributes,
+    # and if so it will only set defaults for those attributes.
+    def setdefaults(*ary)
+        #self.class.eachattr(*ary) { |klass, type|
+        self.class.eachattr(*ary) { |klass, type|
+            # not many attributes will have defaults defined, so we short-circuit
+            # those away
+            next unless klass.method_defined?(:default)
+            next if @parameters[klass.name]
+
+            next unless obj = self.newattr(klass)
+
+            # We have to check for nil values, not "truth", so we allow defaults
+            # to false.
+            value = obj.default and ! value.nil?
+            if ! value.nil?
+                obj.value = value
+            else
+                @parameters.delete(obj.name)
+            end
+        }
+    end
+
+    # Convert our object to a hash.  This just includes properties.
+    def to_hash
+        rethash = {}
+    
+        @parameters.each do |name, obj|
+            rethash[name] = obj.value
+        end
+
+        rethash
+    end
+
+    # Return a specific value for an attribute.
+    def value(name)
+        name = attr_alias(name)
+
+        if obj = @parameters[name] and obj.respond_to?(:value)
+            return obj.value
+        else
+            return nil
+        end
+    end
+
+    # Meta-parameter methods:  These methods deal with the results
+    # of specifying metaparameters
+
+    private
+
+    # Return all of the property objects, in the order specified in the
+    # class.
+    def properties
+        #debug "%s has %s properties" % [self, at parameters.length]
+        props = self.class.properties.collect { |prop|
+            @parameters[prop.name]
+        }.find_all { |p|
+            ! p.nil?
+        }.each do |prop|
+            unless prop.is_a?(Puppet::Property)
+                raise Puppet::DevError, "got a non-property %s(%s)" %
+                    [prop.class, prop.class.name]
+            end
+        end
+
+        props
+    end
+end
+
diff --git a/lib/puppet/metatype/closure.rb b/lib/puppet/metatype/closure.rb
new file mode 100644
index 0000000..673a235
--- /dev/null
+++ b/lib/puppet/metatype/closure.rb
@@ -0,0 +1,49 @@
+class Puppet::Type
+    attr_writer :implicit
+
+    # Is this type's name isomorphic with the object?  That is, if the
+    # name conflicts, does it necessarily mean that the objects conflict?
+    # Defaults to true.
+    def self.isomorphic?
+        if defined? @isomorphic
+            return @isomorphic
+        else
+            return true
+        end
+    end
+
+    def implicit?
+        if defined? @implicit and @implicit
+            return true
+        else
+            return false
+        end
+    end
+
+    def isomorphic?
+        self.class.isomorphic?
+    end
+
+    # is the instance a managed instance?  A 'yes' here means that
+    # the instance was created from the language, vs. being created
+    # in order resolve other questions, such as finding a package
+    # in a list
+    def managed?
+        # Once an object is managed, it always stays managed; but an object
+        # that is listed as unmanaged might become managed later in the process,
+        # so we have to check that every time
+        if defined? @managed and @managed
+            return @managed
+        else
+            @managed = false
+            properties.each { |property|
+                s = property.should
+                if s and ! property.class.unmanaged
+                    @managed = true
+                    break
+                end
+            }
+            return @managed
+        end
+    end
+end
diff --git a/lib/puppet/metatype/container.rb b/lib/puppet/metatype/container.rb
new file mode 100644
index 0000000..2bbe3f5
--- /dev/null
+++ b/lib/puppet/metatype/container.rb
@@ -0,0 +1,50 @@
+class Puppet::Type
+
+    # this is a retarded hack method to get around the difference between
+    # component children and file children
+    def self.depthfirst?
+        if defined? @depthfirst
+            return @depthfirst
+        else
+            return false
+        end
+    end
+    
+    def depthfirst?
+        self.class.depthfirst?
+    end
+
+    # Add a hook for testing for recursion.
+    def parentof?(child)
+        if (self == child)
+            debug "parent is equal to child"
+            return true
+        elsif defined? @parent and @parent.parentof?(child)
+            debug "My parent is parent of child"
+            return true
+        else
+            return false
+        end
+    end
+
+    # Remove an object.  The argument determines whether the object's
+    # subscriptions get eliminated, too.
+    def remove(rmdeps = true)
+        # This is hackish (mmm, cut and paste), but it works for now, and it's
+        # better than warnings.
+        @parameters.each do |name, obj|
+            obj.remove
+        end
+        @parameters.clear
+        self.class.delete(self)
+
+        @parent = nil
+
+        # Remove the reference to the provider.
+        if self.provider
+            @provider.clear
+            @provider = nil
+        end
+    end
+end
+
diff --git a/lib/puppet/metatype/evaluation.rb b/lib/puppet/metatype/evaluation.rb
new file mode 100644
index 0000000..ff1eddb
--- /dev/null
+++ b/lib/puppet/metatype/evaluation.rb
@@ -0,0 +1,163 @@
+class Puppet::Type
+    # This method is responsible for collecting property changes we always
+    # descend into the children before we evaluate our current properties.
+    # This returns any changes resulting from testing, thus 'collect' rather
+    # than 'each'.
+    def evaluate
+        if self.provider.is_a?(Puppet::Provider)
+            unless provider.class.suitable?
+                raise Puppet::Error, "Provider %s is not functional on this platform" % provider.class.name
+            end
+        end
+        #Puppet.err "Evaluating %s" % self.path.join(":")
+        unless defined? @evalcount
+            self.err "No evalcount defined on '%s' of type '%s'" %
+                [self.title,self.class]
+            @evalcount = 0
+        end
+        @evalcount += 1
+
+        if p = self.provider and p.respond_to?(:prefetch)
+            p.prefetch
+        end
+
+        # this only operates on properties, not properties + children
+        # it's important that we call retrieve() on the type instance,
+        # not directly on the property, because it allows the type to override
+        # the method, like pfile does
+        currentvalues = self.retrieve
+
+        changes = propertychanges(currentvalues).flatten
+
+        # now record how many changes we've resulted in
+        if changes.length > 0
+            self.debug "%s change(s)" %
+                [changes.length]
+        end
+
+        # If we're in noop mode, we don't want to store the checked time,
+        # because it will result in the resource not getting scheduled if
+        # someone were to apply the catalog in non-noop mode.
+        # We're going to go ahead and record that we checked if there were
+        # no changes, since it's unlikely it will affect the scheduling.
+        noop = noop?
+        if ! noop or (noop && changes.length == 0)
+            self.cache(:checked, Time.now)
+        end
+        return changes.flatten
+    end
+
+    # Flush the provider, if it supports it.  This is called by the
+    # transaction.
+    def flush
+        if self.provider and self.provider.respond_to?(:flush)
+            self.provider.flush
+        end
+    end
+
+    # if all contained objects are in sync, then we're in sync
+    # FIXME I don't think this is used on the type instances any more,
+    # it's really only used for testing
+    def insync?(is)
+        insync = true
+        
+        if property = @parameters[:ensure]
+            unless is.include? property
+               raise Puppet::DevError,
+                        "The is value is not in the is array for '%s'" %
+                        [property.name]
+            end
+            ensureis = is[property]           
+            if property.insync?(ensureis) and property.should == :absent
+                return true
+            end
+        end
+
+        properties.each { |property|
+            unless is.include? property
+               raise Puppet::DevError,
+                        "The is value is not in the is array for '%s'" %
+                        [property.name]
+            end
+
+            propis = is[property]
+            unless property.insync?(propis)
+                property.debug("Not in sync: %s vs %s" %
+                    [propis.inspect, property.should.inspect])
+                insync = false
+            #else
+            #    property.debug("In sync")
+            end
+        }
+
+        #self.debug("%s sync status is %s" % [self,insync])
+        return insync
+    end
+        
+    # retrieve the current value of all contained properties
+    def retrieve
+         return currentpropvalues
+    end
+    
+    # get a hash of the current properties.  
+    def currentpropvalues(override_value = nil)
+        # it's important to use the method here, as it follows the order
+        # in which they're defined in the object
+        return properties().inject({}) { | prophash, property|
+                   prophash[property] = override_value.nil? ? 
+                                          property.retrieve : 
+                                             override_value
+                   prophash
+               }
+    end
+
+    # Are we running in noop mode?
+    def noop?
+        if defined?(@noop)
+            @noop
+        else
+            Puppet[:noop]
+        end
+    end
+
+    def noop
+        noop?
+    end
+     
+    # Retrieve the changes associated with all of the properties.
+    def propertychanges(currentvalues)
+        # If we are changing the existence of the object, then none of
+        # the other properties matter.
+        changes = []
+        ensureparam = @parameters[:ensure]
+
+        # This allows resource types to have 'ensure' be a parameter, which allows them to
+        # just pass the parameter on to other generated resources.
+        ensureparam = nil unless ensureparam.is_a?(Puppet::Property)
+        if ensureparam && !currentvalues.include?(ensureparam)
+            raise Puppet::DevError, "Parameter ensure defined but missing from current values"
+        end
+
+        if ensureparam and ! ensureparam.insync?(currentvalues[ensureparam])
+            changes << Puppet::PropertyChange.new(ensureparam, currentvalues[ensureparam])
+        # Else, if the 'ensure' property is correctly absent, then do
+        # nothing
+        elsif ensureparam and currentvalues[ensureparam] == :absent
+            return []
+        else
+            changes = properties().find_all { |property|
+                currentvalues[property] ||= :absent
+                ! property.insync?(currentvalues[property])
+            }.collect { |property|
+                Puppet::PropertyChange.new(property, currentvalues[property])
+            }
+        end
+
+        if Puppet[:debug] and changes.length > 0
+            self.debug("Changing " + changes.collect { |ch| ch.property.name }.join(","))
+        end
+
+        changes
+    end
+end
+
diff --git a/lib/puppet/metatype/instances.rb b/lib/puppet/metatype/instances.rb
new file mode 100644
index 0000000..3f44413
--- /dev/null
+++ b/lib/puppet/metatype/instances.rb
@@ -0,0 +1,305 @@
+require 'puppet/transportable'
+
+class Puppet::Type
+    # Make 'new' private, so people have to use create instead.
+    class << self
+        private :new
+    end
+
+    # retrieve a named instance of the current type
+    def self.[](name)
+        @objects[name] || @aliases[name]
+    end
+
+    # add an instance by name to the class list of instances
+    def self.[]=(name,object)
+        newobj = nil
+        if object.is_a?(Puppet::Type)
+            newobj = object
+        else
+            raise Puppet::DevError, "must pass a Puppet::Type object"
+        end
+
+        if exobj = @objects[name] and self.isomorphic?
+            msg = "Object '%s[%s]' already exists" %
+                [newobj.class.name, name]
+
+            if exobj.file and exobj.line
+                msg += ("in file %s at line %s" %
+                    [object.file, object.line])
+            end
+            if object.file and object.line
+                msg += ("and cannot be redefined in file %s at line %s" %
+                    [object.file, object.line])
+            end
+            error = Puppet::Error.new(msg)
+            raise error
+        else
+            #Puppet.info("adding %s of type %s to class list" %
+            #    [name,object.class])
+            @objects[name] = newobj
+        end
+    end
+
+    # Create an alias.  We keep these in a separate hash so that we don't encounter
+    # the objects multiple times when iterating over them.
+    def self.alias(name, obj)
+        if @objects.include?(name)
+            unless @objects[name] == obj
+                raise Puppet::Error.new(
+                    "Cannot create alias %s: object already exists" %
+                    [name]
+                )
+            end
+        end
+
+        if @aliases.include?(name)
+            unless @aliases[name] == obj
+                raise Puppet::Error.new(
+                    "Object %s already has alias %s" %
+                    [@aliases[name].name, name]
+                )
+            end
+        end
+
+        @aliases[name] = obj
+    end
+
+    # remove all of the instances of a single type
+    def self.clear
+        if defined? @objects
+            @objects.each do |name, obj|
+                obj.remove(true)
+            end
+            @objects.clear
+        end
+        if defined? @aliases
+            @aliases.clear
+        end
+    end
+
+    # Force users to call this, so that we can merge objects if
+    # necessary.
+    def self.create(args)
+        # Don't modify the original hash; instead, create a duplicate and modify it.
+        # We have to dup and use the ! so that it stays a TransObject if it is
+        # one.
+        hash = args.dup
+        symbolizehash!(hash)
+
+        # If we're the base class, then pass the info on appropriately
+        if self == Puppet::Type
+            type = nil
+            if hash.is_a? Puppet::TransObject
+                type = hash.type
+            else
+                # If we're using the type to determine object type, then delete it
+                if type = hash[:type]
+                    hash.delete(:type)
+                end
+            end
+
+            # If they've specified a type and called on the base, then
+            # delegate to the subclass.
+            if type
+                if typeklass = self.type(type)
+                    return typeklass.create(hash)
+                else
+                    raise Puppet::Error, "Unknown type %s" % type
+                end
+            else
+                raise Puppet::Error, "No type found for %s" % hash.inspect
+            end
+        end
+
+        # Handle this new object being implicit
+        implicit = hash[:implicit] || false
+        if hash.include?(:implicit)
+            hash.delete(:implicit)
+        end
+
+        name = nil
+        unless hash.is_a? Puppet::TransObject
+            hash = self.hash2trans(hash)
+        end
+
+        # XXX This will have to change when transobjects change to using titles
+        title = hash.name
+
+        # if the object already exists
+        if self.isomorphic? and retobj = self[title]
+            # if only one of our objects is implicit, then it's easy to see
+            # who wins -- the non-implicit one.
+            if retobj.implicit? and ! implicit
+                Puppet.notice "Removing implicit %s" % retobj.title
+                # Remove all of the objects, but do not remove their subscriptions.
+                retobj.remove(false)
+
+                # now pass through and create the new object
+            elsif implicit
+                Puppet.debug "Ignoring implicit %s[%s]" % [self.name, title]
+                return nil
+            else
+                raise Puppet::Error, "%s is already being managed" % retobj.ref
+            end
+        end
+
+        # create it anew
+        # if there's a failure, destroy the object if it got that far, but raise
+        # the error.
+        begin
+            obj = new(hash)
+        rescue => detail
+            Puppet.err "Could not create %s: %s" % [title, detail.to_s]
+            if obj
+                obj.remove(true)
+            elsif obj = self[title]
+                obj.remove(true)
+            end
+            raise
+        end
+
+        if implicit
+            obj.implicit = true
+        end
+
+        # Store the object by title
+        self[obj.title] = obj
+
+        return obj
+    end
+
+    # remove a specified object
+    def self.delete(resource)
+        return unless defined? @objects
+        if @objects.include?(resource.title)
+            @objects.delete(resource.title)
+        end
+        if @aliases.include?(resource.title)
+            @aliases.delete(resource.title)
+        end
+        if @aliases.has_value?(resource)
+            names = []
+            @aliases.each do |name, otherres|
+                if otherres == resource
+                    names << name
+                end
+            end
+            names.each { |name| @aliases.delete(name) }
+        end
+    end
+
+    # iterate across each of the type's instances
+    def self.each
+        return unless defined? @objects
+        @objects.each { |name,instance|
+            yield instance
+        }
+    end
+
+    # does the type have an object with the given name?
+    def self.has_key?(name)
+        return @objects.has_key?(name)
+    end
+
+    # Convert a hash to a TransObject.
+    def self.hash2trans(hash)
+        title = nil
+        if hash.include? :title
+            title = hash[:title]
+            hash.delete(:title)
+        elsif hash.include? self.namevar
+            title = hash[self.namevar]
+            hash.delete(self.namevar)
+
+            if hash.include? :name
+                raise ArgumentError, "Cannot provide both name and %s to %s" %
+                    [self.namevar, self.name]
+            end
+        elsif hash[:name]
+            title = hash[:name]
+            hash.delete :name
+        end
+
+        if catalog = hash[:catalog]
+            hash.delete(:catalog)
+        end
+
+        raise(Puppet::Error, "You must specify a title for objects of type %s" % self.to_s) unless title
+
+        if hash.include? :type
+            unless self.validattr? :type
+                hash.delete :type
+            end
+        end
+
+        # okay, now make a transobject out of hash
+        begin
+            trans = Puppet::TransObject.new(title, self.name.to_s)
+            trans.catalog = catalog if catalog
+            hash.each { |param, value|
+                trans[param] = value
+            }
+        rescue => detail
+            raise Puppet::Error, "Could not create %s: %s" %
+                [name, detail]
+        end
+
+        return trans
+    end
+
+    # Retrieve all known instances.  Either requires providers or must be overridden.
+    def self.instances
+        unless defined?(@providers) and ! @providers.empty?
+            raise Puppet::DevError, "%s has no providers and has not overridden 'instances'" % self.name
+        end
+
+        # Put the default provider first, then the rest of the suitable providers.
+        provider_instances = {}
+        providers_by_source.collect do |provider|
+            provider.instances.collect do |instance|
+                # First try to get the resource if it already exists
+                # Skip instances that map to a managed resource with a different provider
+                next if resource = self[instance.name] and resource.provider.class != instance.class
+
+                # We always want to use the "first" provider instance we find, unless the resource
+                # is already managed and has a different provider set
+                if other = provider_instances[instance.name]
+                    Puppet.warning "%s %s found in both %s and %s; skipping the %s version" %
+                        [self.name.to_s.capitalize, instance.name, other.class.name, instance.class.name, instance.class.name]
+                    next
+                end
+                provider_instances[instance.name] = instance
+
+                if resource
+                    resource.provider = instance
+                    resource
+                else
+                    create(:name => instance.name, :provider => instance, :check => :all)
+                end
+            end
+        end.flatten.compact
+    end
+
+    # Return a list of one suitable provider per source, with the default provider first.
+    def self.providers_by_source
+        # Put the default provider first, then the rest of the suitable providers.
+        sources = []
+        [defaultprovider, suitableprovider].flatten.uniq.collect do |provider|
+            next if sources.include?(provider.source)
+
+            sources << provider.source
+            provider
+        end.compact
+    end
+
+    # Create the path for logging and such.
+    def pathbuilder
+        if p = parent
+            [p.pathbuilder, self.ref].flatten
+        else
+            [self.ref]
+        end
+    end
+end
+
diff --git a/lib/puppet/metatype/metaparams.rb b/lib/puppet/metatype/metaparams.rb
new file mode 100644
index 0000000..edd5941
--- /dev/null
+++ b/lib/puppet/metatype/metaparams.rb
@@ -0,0 +1,423 @@
+require 'puppet'
+require 'puppet/type'
+
+class Puppet::Type
+    # Add all of the meta parameters.
+    #newmetaparam(:onerror) do
+    #    desc "How to handle errors -- roll back innermost
+    #        transaction, roll back entire transaction, ignore, etc.  Currently
+    #        non-functional."
+    #end
+
+    newmetaparam(:noop) do
+        desc "Boolean flag indicating whether work should actually
+            be done."
+            
+        newvalues(:true, :false)
+        munge do |value|
+            case value
+            when true, :true, "true": @resource.noop = true
+            when false, :false, "false": @resource.noop = false
+            end
+        end
+    end
+
+    newmetaparam(:schedule) do
+        desc "On what schedule the object should be managed.  You must create a
+            schedule object, and then reference the name of that object to use
+            that for your schedule::
+
+                schedule { daily:
+                    period => daily,
+                    range => \"2-4\"
+                }
+
+                exec { \"/usr/bin/apt-get update\":
+                    schedule => daily
+                }
+
+            The creation of the schedule object does not need to appear in the
+            configuration before objects that use it."
+    end
+
+    newmetaparam(:check) do
+        desc "Propertys which should have their values retrieved
+            but which should not actually be modified.  This is currently used
+            internally, but will eventually be used for querying, so that you
+            could specify that you wanted to check the install state of all
+            packages, and then query the Puppet client daemon to get reports
+            on all packages."
+
+        munge do |args|
+            # If they've specified all, collect all known properties
+            if args == :all
+                args = @resource.class.properties.find_all do |property|
+                    # Only get properties supported by our provider
+                    if @resource.provider
+                        @resource.provider.class.supports_parameter?(property)
+                    else
+                        true
+                    end
+                end.collect do |property|
+                    property.name
+                end
+            end
+
+            unless args.is_a?(Array)
+                args = [args]
+            end
+
+            unless defined? @resource
+                self.devfail "No parent for %s, %s?" %
+                    [self.class, self.name]
+            end
+
+            args.each { |property|
+                unless property.is_a?(Symbol)
+                    property = property.intern
+                end
+                next if @resource.propertydefined?(property)
+
+                unless propertyklass = @resource.class.validproperty?(property)
+                    if @resource.class.validattr?(property)
+                        next
+                    else
+                        raise Puppet::Error, "%s is not a valid attribute for %s" %
+                            [property, self.class.name]
+                    end
+                end
+                next unless propertyklass.checkable?
+                @resource.newattr(property)
+            }
+        end
+    end
+    
+    # We've got four relationship metaparameters, so this method is used
+    # to reduce code duplication between them.
+    def munge_relationship(param, values)
+        # We need to support values passed in as an array or as a
+        # resource reference.
+        result = []
+        
+        # 'values' could be an array or a reference.  If it's an array,
+        # it could be an array of references or an array of arrays.
+        if values.is_a?(Puppet::Type)
+            result << [values.class.name, values.title]
+        else
+            unless values.is_a?(Array)
+                devfail "Relationships must be resource references"
+            end
+            if values[0].is_a?(String) or values[0].is_a?(Symbol)
+                # we're a type/title array reference
+                values[0] = symbolize(values[0])
+                result << values
+            else
+                # we're an array of stuff
+                values.each do |value|
+                    if value.is_a?(Puppet::Type)
+                        result << [value.class.name, value.title]
+                    elsif value.is_a?(Array)
+                        value[0] = symbolize(value[0])
+                        result << value
+                    else
+                        devfail "Invalid relationship %s" % value.inspect
+                    end
+                end
+            end
+        end
+        
+        if existing = self[param]
+            result = existing + result
+        end
+        
+        result
+    end
+
+    newmetaparam(:loglevel) do
+        desc "Sets the level that information will be logged.
+             The log levels have the biggest impact when logs are sent to
+             syslog (which is currently the default)."
+        defaultto :notice
+
+        newvalues(*Puppet::Util::Log.levels)
+        newvalues(:verbose)
+
+        munge do |loglevel|
+            val = super(loglevel)
+            if val == :verbose
+                val = :info 
+            end        
+            val
+        end
+    end
+
+    newmetaparam(:alias) do
+        desc "Creates an alias for the object.  Puppet uses this internally when you
+            provide a symbolic name::
+            
+                file { sshdconfig:
+                    path => $operatingsystem ? {
+                        solaris => \"/usr/local/etc/ssh/sshd_config\",
+                        default => \"/etc/ssh/sshd_config\"
+                    },
+                    source => \"...\"
+                }
+
+                service { sshd:
+                    subscribe => file[sshdconfig]
+                }
+
+            When you use this feature, the parser sets ``sshdconfig`` as the name,
+            and the library sets that as an alias for the file so the dependency
+            lookup for ``sshd`` works.  You can use this parameter yourself,
+            but note that only the library can use these aliases; for instance,
+            the following code will not work::
+
+                file { \"/etc/ssh/sshd_config\":
+                    owner => root,
+                    group => root,
+                    alias => sshdconfig
+                }
+
+                file { sshdconfig:
+                    mode => 644
+                }
+
+            There's no way here for the Puppet parser to know that these two stanzas
+            should be affecting the same file.
+
+            See the `LanguageTutorial language tutorial`:trac: for more information.
+            
+            "
+
+        munge do |aliases|
+            unless aliases.is_a?(Array)
+                aliases = [aliases]
+            end
+
+            raise(ArgumentError, "Cannot add aliases without a catalog") unless @resource.catalog
+
+            @resource.info "Adding aliases %s" % aliases.collect { |a| a.inspect }.join(", ")
+
+            aliases.each do |other|
+                if obj = @resource.catalog.resource(@resource.class.name, other)
+                    unless obj.object_id == @resource.object_id
+                        self.fail("%s can not create alias %s: object already exists" % [@resource.title, other])
+                    end
+                    next
+                end
+
+                # LAK:FIXME Old-school, add the alias to the class.
+                @resource.class.alias(other, @resource)
+
+                # Newschool, add it to the catalog.
+                @resource.catalog.alias(@resource, other)
+            end
+        end
+    end
+
+    newmetaparam(:tag) do
+        desc "Add the specified tags to the associated resource.  While all resources
+            are automatically tagged with as much information as possible
+            (e.g., each class and definition containing the resource), it can
+            be useful to add your own tags to a given resource.
+
+            Tags are currently useful for things like applying a subset of a
+            host's configuration::
+                
+                puppetd --test --tags mytag
+
+            This way, when you're testing a configuration you can run just the
+            portion you're testing."
+
+        munge do |tags|
+            tags = [tags] unless tags.is_a? Array
+
+            tags.each do |tag|
+                @resource.tag(tag)
+            end
+        end
+    end
+    
+    class RelationshipMetaparam < Puppet::Parameter
+        class << self
+            attr_accessor :direction, :events, :callback, :subclasses
+        end
+        
+        @subclasses = []
+        
+        def self.inherited(sub)
+            @subclasses << sub
+        end
+        
+        def munge(rels)
+            @resource.munge_relationship(self.class.name, rels)
+        end
+
+        def validate_relationship
+            @value.each do |value|
+                unless @resource.catalog.resource(*value)
+                    description = self.class.direction == :in ? "dependency" : "dependent"
+                    fail Puppet::Error, "Could not find #{description} %s[%s] for %s" % [value[0].to_s.capitalize, value[1], resource.ref]
+                end
+            end
+        end
+        
+        # Create edges from each of our relationships.    :in
+        # relationships are specified by the event-receivers, and :out
+        # relationships are specified by the event generator.  This
+        # way 'source' and 'target' are consistent terms in both edges
+        # and events -- that is, an event targets edges whose source matches
+        # the event's source.  The direction of the relationship determines
+        # which resource is applied first and which resource is considered
+        # to be the event generator.
+        def to_edges
+            @value.collect do |value|
+                # we just have a name and a type, and we need to convert it
+                # to an object...
+                tname, name = value
+                reference = Puppet::ResourceReference.new(tname, name)
+                
+                # Either of the two retrieval attempts could have returned
+                # nil.
+                unless object = reference.resolve
+                    self.fail "Could not retrieve dependency '%s' of %s" % [reference, @resource.ref]
+                end
+
+                # Are we requiring them, or vice versa?  See the method docs
+                # for futher info on this.
+                if self.class.direction == :in
+                    source = object
+                    target = @resource
+                else
+                    source = @resource
+                    target = object
+                end
+
+                if method = self.class.callback
+                    subargs = {
+                        :event => self.class.events,
+                        :callback => method
+                    }
+                    self.debug("subscribes to %s" % [object.ref])
+                else
+                    # If there's no callback, there's no point in even adding
+                    # a label.
+                    subargs = nil
+                    self.debug("requires %s" % [object.ref])
+                end
+                
+                rel = Puppet::Relationship.new(source, target, subargs)
+            end
+        end
+    end
+    
+    def self.relationship_params
+        RelationshipMetaparam.subclasses
+    end
+
+
+    # Note that the order in which the relationships params is defined
+    # matters.  The labelled params (notify and subcribe) must be later,
+    # so that if both params are used, those ones win.  It's a hackish
+    # solution, but it works.
+
+    newmetaparam(:require, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :NONE}) do
+        desc "One or more objects that this object depends on.
+            This is used purely for guaranteeing that changes to required objects
+            happen before the dependent object.  For instance::
+            
+                # Create the destination directory before you copy things down
+                file { \"/usr/local/scripts\":
+                    ensure => directory
+                }
+
+                file { \"/usr/local/scripts/myscript\":
+                    source => \"puppet://server/module/myscript\",
+                    mode => 755,
+                    require => File[\"/usr/local/scripts\"]
+                }
+
+            Multiple dependencies can be specified by providing a comma-seperated list
+            of resources, enclosed in square brackets::
+
+                require => [ File[\"/usr/local\"], File[\"/usr/local/scripts\"] ]
+
+            Note that Puppet will autorequire everything that it can, and
+            there are hooks in place so that it's easy for resources to add new
+            ways to autorequire objects, so if you think Puppet could be
+            smarter here, let us know.
+
+            In fact, the above code was redundant -- Puppet will autorequire
+            any parent directories that are being managed; it will
+            automatically realize that the parent directory should be created
+            before the script is pulled down.
+            
+            Currently, exec resources will autorequire their CWD (if it is
+            specified) plus any fully qualified paths that appear in the
+            command.   For instance, if you had an ``exec`` command that ran
+            the ``myscript`` mentioned above, the above code that pulls the
+            file down would be automatically listed as a requirement to the
+            ``exec`` code, so that you would always be running againts the
+            most recent version.
+            "
+    end
+
+    newmetaparam(:subscribe, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :ALL_EVENTS, :callback => :refresh}) do
+        desc "One or more objects that this object depends on.  Changes in the
+            subscribed to objects result in the dependent objects being
+            refreshed (e.g., a service will get restarted).  For instance::
+            
+                class nagios {
+                    file { \"/etc/nagios/nagios.conf\":
+                        source => \"puppet://server/module/nagios.conf\",
+                        alias => nagconf # just to make things easier for me
+                    }
+                    service { nagios:
+                        running => true,
+                        subscribe => File[nagconf]
+                    }
+                }
+	 		
+            Currently the ``exec``, ``mount`` and ``service`` type support
+            refreshing.
+            "
+    end
+
+    newmetaparam(:before, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :NONE}) do
+        desc %{This parameter is the opposite of **require** -- it guarantees
+            that the specified object is applied later than the specifying
+            object::
+
+                file { "/var/nagios/configuration":
+                    source  => "...",
+                    recurse => true,
+                    before => Exec["nagios-rebuid"]
+                }
+
+                exec { "nagios-rebuild":
+                    command => "/usr/bin/make",
+                    cwd => "/var/nagios/configuration"
+                }
+            
+            This will make sure all of the files are up to date before the
+            make command is run.}
+    end
+    
+    newmetaparam(:notify, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :ALL_EVENTS, :callback => :refresh}) do
+        desc %{This parameter is the opposite of **subscribe** -- it sends events
+            to the specified object::
+
+                file { "/etc/sshd_config":
+                    source => "....",
+                    notify => Service[sshd]
+                }
+
+                service { sshd:
+                    ensure => running
+                }
+            
+            This will restart the sshd service if the sshd config file changes.}
+    end
+end # Puppet::Type
+
diff --git a/lib/puppet/metatype/providers.rb b/lib/puppet/metatype/providers.rb
new file mode 100644
index 0000000..6308f7e
--- /dev/null
+++ b/lib/puppet/metatype/providers.rb
@@ -0,0 +1,247 @@
+require 'puppet/provider'
+require 'puppet/util/provider_features'
+class Puppet::Type
+    # Add the feature handling module.
+    extend Puppet::Util::ProviderFeatures
+
+    attr_reader :provider
+
+    # the Type class attribute accessors
+    class << self
+        attr_accessor :providerloader
+        attr_writer :defaultprovider
+    end
+
+    # Find the default provider.
+    def self.defaultprovider
+        unless defined? @defaultprovider and @defaultprovider
+            suitable = suitableprovider()
+
+            # Find which providers are a default for this system.
+            defaults = suitable.find_all { |provider| provider.default? }
+
+            # If we don't have any default we use suitable providers
+            defaults = suitable if defaults.empty?
+            max = defaults.collect { |provider| provider.defaultnum }.max
+            defaults = defaults.find_all { |provider| provider.defaultnum == max }
+
+            retval = nil
+            if defaults.length > 1
+                Puppet.warning(
+                    "Found multiple default providers for %s: %s; using %s" %
+                    [self.name, defaults.collect { |i| i.name.to_s }.join(", "),
+                        defaults[0].name]
+                )
+                retval = defaults.shift
+            elsif defaults.length == 1
+                retval = defaults.shift
+            else
+                raise Puppet::DevError, "Could not find a default provider for %s" %
+                    self.name
+            end
+
+            @defaultprovider = retval
+        end
+
+        return @defaultprovider
+    end
+
+    # Convert a hash, as provided by, um, a provider, into an instance of self.
+    def self.hash2obj(hash)
+        obj = nil
+        
+        namevar = self.namevar
+        unless hash.include?(namevar) and hash[namevar]
+            raise Puppet::DevError, "Hash was not passed with namevar"
+        end
+
+        # if the obj already exists with that name...
+        if obj = self[hash[namevar]]
+            # We're assuming here that objects with the same name
+            # are the same object, which *should* be the case, assuming
+            # we've set up our naming stuff correctly everywhere.
+
+            # Mark found objects as present
+            hash.each { |param, value|
+                if property = obj.property(param)
+                elsif val = obj[param]
+                    obj[param] = val
+                else
+                    # There is a value on disk, but it should go away
+                    obj[param] = :absent
+                end
+            }
+        else
+            # create a new obj, since no existing one seems to
+            # match
+            obj = self.create(namevar => hash[namevar])
+
+            # We can't just pass the hash in at object creation time,
+            # because it sets the should value, not the is value.
+            hash.delete(namevar)
+            hash.each { |param, value|
+                obj[param] = value unless obj.add_property_parameter(param)
+            }
+        end
+
+        return obj
+    end
+
+    # Retrieve a provider by name.
+    def self.provider(name)
+        name = Puppet::Util.symbolize(name)
+
+        # If we don't have it yet, try loading it.
+        unless @providers.has_key?(name)
+            @providerloader.load(name)
+        end
+        return @providers[name]
+    end
+
+    # Just list all of the providers.
+    def self.providers
+        @providers.keys
+    end
+
+    def self.validprovider?(name)
+        name = Puppet::Util.symbolize(name)
+
+        return (@providers.has_key?(name) && @providers[name].suitable?)
+    end
+
+    # Create a new provider of a type.  This method must be called
+    # directly on the type that it's implementing.
+    def self.provide(name, options = {}, &block)
+        name = Puppet::Util.symbolize(name)
+
+        if obj = @providers[name]
+            Puppet.debug "Reloading %s %s provider" % [name, self.name]
+            unprovide(name)
+        end
+
+        parent = if pname = options[:parent]
+            options.delete(:parent)
+            if pname.is_a? Class
+                pname
+            else
+                if provider = self.provider(pname)
+                    provider
+                else
+                    raise Puppet::DevError,
+                        "Could not find parent provider %s of %s" %
+                            [pname, name]
+                end
+            end
+        else
+            Puppet::Provider
+        end
+
+        options[:resource_type] ||= self
+
+        self.providify
+
+        provider = genclass(name,
+            :parent => parent,
+            :hash => @providers,
+            :prefix => "Provider",
+            :block => block,
+            :include => feature_module,
+            :extend => feature_module,
+            :attributes => options
+        )
+
+        return provider
+    end
+
+    # Make sure we have a :provider parameter defined.  Only gets called if there
+    # are providers.
+    def self.providify
+        return if @paramhash.has_key? :provider
+
+        newparam(:provider) do
+            desc "The specific backend for #{self.name.to_s} to use. You will
+                seldom need to specify this -- Puppet will usually discover the
+                appropriate provider for your platform."
+
+            # This is so we can refer back to the type to get a list of
+            # providers for documentation.
+            class << self
+                attr_accessor :parenttype
+            end
+
+            # We need to add documentation for each provider.
+            def self.doc
+                @doc + "  Available providers are:\n\n" + parenttype().providers.sort { |a,b|
+                    a.to_s <=> b.to_s
+                }.collect { |i|
+                    "* **%s**: %s" % [i, parenttype().provider(i).doc]
+                }.join("\n")
+            end
+
+            defaultto {
+                @resource.class.defaultprovider.name
+            }
+
+            validate do |provider_class|
+                provider_class = provider_class[0] if provider_class.is_a? Array
+                if provider_class.is_a?(Puppet::Provider)
+                    provider_class = provider_class.class.name
+                end
+
+                unless provider = @resource.class.provider(provider_class)
+                    raise ArgumentError, "Invalid %s provider '%s'" % [@resource.class.name, provider_class]
+                end
+            end
+
+            munge do |provider|
+                provider = provider[0] if provider.is_a? Array
+                if provider.is_a? String
+                    provider = provider.intern
+                end
+                @resource.provider = provider
+
+                if provider.is_a?(Puppet::Provider)
+                    provider.class.name
+                else
+                    provider
+                end
+            end
+        end.parenttype = self
+    end
+
+    def self.unprovide(name)
+        if @providers.has_key? name
+            rmclass(name,
+                :hash => @providers,
+                :prefix => "Provider"
+            )
+            if @defaultprovider and @defaultprovider.name == name
+                @defaultprovider = nil
+            end
+        end
+    end
+
+    # Return an array of all of the suitable providers.
+    def self.suitableprovider
+        if @providers.empty?
+            providerloader.loadall
+        end
+        @providers.find_all { |name, provider|
+            provider.suitable?
+        }.collect { |name, provider|
+            provider
+        }.reject { |p| p.name == :fake } # For testing
+    end
+
+    def provider=(name)
+        if name.is_a?(Puppet::Provider)
+            @provider = name
+            @provider.resource = self
+        elsif klass = self.class.provider(name)
+            @provider = klass.new(self)
+        else
+            raise ArgumentError, "Could not find %s provider of %s" %
+                [name, self.class.name]
+        end
+    end
+end
diff --git a/lib/puppet/metatype/relationships.rb b/lib/puppet/metatype/relationships.rb
new file mode 100644
index 0000000..4fb78ae
--- /dev/null
+++ b/lib/puppet/metatype/relationships.rb
@@ -0,0 +1,115 @@
+class Puppet::Type
+    # Specify a block for generating a list of objects to autorequire.  This
+    # makes it so that you don't have to manually specify things that you clearly
+    # require.
+    def self.autorequire(name, &block)
+        @autorequires ||= {}
+        @autorequires[name] = block
+    end
+
+    # Yield each of those autorequires in turn, yo.
+    def self.eachautorequire
+        @autorequires ||= {}
+        @autorequires.each { |type, block|
+            yield(type, block)
+        }
+    end
+
+    # Figure out of there are any objects we can automatically add as
+    # dependencies.
+    def autorequire
+        reqs = []
+        self.class.eachautorequire { |type, block|
+            # Ignore any types we can't find, although that would be a bit odd.
+            next unless typeobj = Puppet.type(type)
+
+            # Retrieve the list of names from the block.
+            next unless list = self.instance_eval(&block)
+            unless list.is_a?(Array)
+                list = [list]
+            end
+
+            # Collect the current prereqs
+            list.each { |dep|
+                obj = nil
+                # Support them passing objects directly, to save some effort.
+                unless dep.is_a? Puppet::Type
+                    # Skip autorequires that we aren't managing
+                    unless dep = typeobj[dep]
+                        next
+                    end
+                end
+                
+                reqs << Puppet::Relationship.new(dep, self)
+            }
+        }
+        
+        return reqs
+    end
+
+    # Build the dependencies associated with an individual object.
+    def builddepends
+        # Handle the requires
+        self.class.relationship_params.collect do |klass|
+            if param = @parameters[klass.name]
+                param.to_edges
+            end
+        end.flatten.reject { |r| r.nil? }
+    end
+    
+    # Does this resource have a relationship with the other?  We have to
+    # check each object for both directions of relationship.
+    def requires?(other)
+        them = [other.class.name, other.title]
+        me = [self.class.name, self.title]
+        self.class.relationship_params.each do |param|
+            case param.direction
+            when :in: return true if v = self[param.name] and v.include?(them)
+            when :out: return true if v = other[param.name] and v.include?(me)
+            end
+        end
+        return false
+    end
+
+    # we've received an event
+    # we only support local events right now, so we can pass actual
+    # objects around, including the transaction object
+    # the assumption here is that container objects will pass received
+    # methods on to contained objects
+    # i.e., we don't trigger our children, our refresh() method calls
+    # refresh() on our children
+    def trigger(event, source)
+        trans = event.transaction
+        if @callbacks.include?(source)
+            [:ALL_EVENTS, event.event].each { |eventname|
+                if method = @callbacks[source][eventname]
+                    if trans.triggered?(self, method) > 0
+                        next
+                    end
+                    if self.respond_to?(method)
+                        self.send(method)
+                    end
+
+                    trans.triggered(self, method)
+                end
+            }
+        end
+    end
+    
+    # Unsubscribe from a given object, possibly with a specific event.
+    def unsubscribe(object, event = nil)
+        # First look through our own relationship params
+        [:require, :subscribe].each do |param|
+            if values = self[param]
+                newvals = values.reject { |d|
+                    d == [object.class.name, object.title]
+                }
+                if newvals.length != values.length
+                    self.delete(param)
+                    self[param] = newvals
+                end
+            end
+        end
+    end
+end
+
diff --git a/lib/puppet/metatype/schedules.rb b/lib/puppet/metatype/schedules.rb
new file mode 100644
index 0000000..96ebce0
--- /dev/null
+++ b/lib/puppet/metatype/schedules.rb
@@ -0,0 +1,33 @@
+class Puppet::Type
+    # Look up the schedule and set it appropriately.  This is done after
+    # the instantiation phase, so that the schedule can be anywhere in the
+    # file.
+    def schedule
+        unless defined? @schedule
+            if name = self[:schedule]
+                if sched = Puppet.type(:schedule)[name]
+                    @schedule = sched
+                else
+                    self.fail "Could not find schedule %s" % name
+                end
+            else
+                @schedule = nil
+            end
+        end
+        @schedule
+    end
+
+    # Check whether we are scheduled to run right now or not.
+    def scheduled?
+        return true if Puppet[:ignoreschedules]
+        return true unless schedule = self.schedule
+
+        # We use 'checked' here instead of 'synced' because otherwise we'll
+        # end up checking most resources most times, because they will generally
+        # have been synced a long time ago (e.g., a file only gets updated
+        # once a month on the server and its schedule is daily; the last sync time
+        # will have been a month ago, so we'd end up checking every run).
+        return schedule.match?(self.cached(:checked).to_i)
+    end
+end
+
diff --git a/lib/puppet/metatype/tags.rb b/lib/puppet/metatype/tags.rb
new file mode 100644
index 0000000..1d96306
--- /dev/null
+++ b/lib/puppet/metatype/tags.rb
@@ -0,0 +1,38 @@
+class Puppet::Type
+    attr_reader :tags
+
+    # Add a new tag.
+    def tag(tag)
+        tag = tag.intern if tag.is_a? String
+        unless @tags.include? tag
+            @tags << tag
+        end
+    end
+
+    # Define the initial list of tags.
+    def tags=(list)
+        list = [list] unless list.is_a? Array
+
+        @tags = list.collect do |t|
+            case t
+            when String: t.intern
+            when Symbol: t
+            else
+                self.warning "Ignoring tag %s of type %s" % [tag.inspect, tag.class]
+            end
+        end
+
+        @tags << self.class.name unless @tags.include?(self.class.name)
+    end
+
+    # Figure out of any of the specified tags apply to this object.  This is an
+    # OR operation.
+    def tagged?(tags)
+        tags = [tags] unless tags.is_a? Array
+
+        tags = tags.collect { |t| t.intern }
+
+        return tags.find { |tag| @tags.include? tag }
+    end
+end
+
diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb
index 9385812..b869316 100644
--- a/lib/puppet/module.rb
+++ b/lib/puppet/module.rb
@@ -19,15 +19,6 @@ class Puppet::Module
         end
     end
 
-    # Return an array of paths by splitting the +templatedir+ config
-    # parameter.
-    def self.templatepath(environment = nil)
-        dirs = Puppet.settings.value(:templatedir, environment).split(":")
-        dirs.select do |p|
-            p =~ /^#{File::SEPARATOR}/ && File::directory?(p)
-        end
-    end
-
     # Find and return the +module+ that +path+ belongs to. If +path+ is
     # absolute, or if there is no module whose name is the first component
     # of +path+, return +nil+
@@ -72,39 +63,21 @@ class Puppet::Module
             return template
         end
 
-        template_paths = templatepath(environment)
-        if template_paths
-            # If we can find the template in :templatedir, we return that.
-            td_file = template_paths.collect { |path|
-                File::join(path, template)
-            }.find { |f| File.exists?(f) }
-
-            return td_file unless td_file == nil
-        end
-
-        td_file = find_template_for_module(template, environment)
-
-        # check in the default template dir, if there is one
-        if td_file.nil?
-            raise Puppet::Error, "No valid template directory found, please check templatedir settings" if template_paths.nil?
-            td_file = File::join(template_paths.first, template)
-        end
-        td_file
-    end
-
-    def self.find_template_for_module(template, environment = nil)
         path, file = split_path(template)
 
         # Because templates don't have an assumed template name, like manifests do,
         # we treat templates with no name as being templates in the main template
         # directory.
-        if not file.nil?
+        if file.nil?
+            mod = nil
+        else
             mod = find(path, environment)
-            if mod
-                return mod.template(file)
-            end
         end
-        nil
+        if mod
+            return mod.template(file)
+        else
+            return File.join(Puppet.settings.value(:templatedir, environment), template)
+        end
     end
 
     # Return a list of manifests (as absolute filenames) that match +pat+
@@ -167,5 +140,4 @@ class Puppet::Module
     end
 
     private :initialize
-    private_class_method :find_template_for_module
 end
diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb
index 5e9422b..22bb3fa 100644
--- a/lib/puppet/network/client/master.rb
+++ b/lib/puppet/network/client/master.rb
@@ -26,20 +26,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
         
         down = Puppet[:downcasefacts]
 
-        Facter.clear
-
-        # Reload everything.
-        if Facter.respond_to? :loadfacts
-            Facter.loadfacts
-        elsif Facter.respond_to? :load
-            Facter.load
-        else
-            Puppet.warning "You should upgrade your version of Facter to at least 1.3.8"
-        end
-
-        # This loads all existing facts and any new ones.  We have to remove and
-        # reload because there's no way to unload specific facts.
-        loadfacts()
         facts = Facter.to_hash.inject({}) do |newhash, array|
             name, fact = array
             if down
@@ -129,9 +115,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
     def getconfig
         dostorage()
 
-        # Retrieve the plugins.
-        getplugins() if Puppet[:pluginsync]
-
         facts = nil
         Puppet::Util.benchmark(:debug, "Retrieved facts") do
             facts = self.class.facts
@@ -139,24 +122,22 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
 
         raise Puppet::Network::ClientError.new("Could not retrieve any facts") unless facts.length > 0
 
+        # Retrieve the plugins.
+        getplugins() if Puppet[:pluginsync]
+
         Puppet.debug("Retrieving catalog")
 
         # If we can't retrieve the catalog, just return, which will either
         # fail, or use the in-memory catalog.
-        unless marshalled_objects = get_actual_config(facts)
+        unless yaml_objects = get_actual_config(facts)
             use_cached_config(true)
             return
         end
 
         begin
-            case Puppet[:catalog_format]
-            when "marshal": objects = Marshal.load(marshalled_objects)
-            when "yaml": objects = YAML.load(marshalled_objects)
-            else
-                raise "Invalid catalog format '%s'" % Puppet[:catalog_format]
-            end
+            objects = YAML.load(yaml_objects)
         rescue => detail
-            msg = "Configuration could not be translated from %s" % Puppet[:catalog_format]
+            msg = "Configuration could not be translated from yaml"
             msg += "; using cached catalog" if use_cached_config(true)
             Puppet.warning msg
             return
@@ -180,7 +161,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
         end
 
         if ! @catalog.from_cache
-            self.cache(marshalled_objects)
+            self.cache(yaml_objects)
         end
 
         # Keep the state database up to date.
@@ -199,7 +180,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
 
         self.class.instance = self
         @running = false
-        @splayed = false
     end
 
     # Mark that we should restart.  The Puppet module checks whether we're running,
@@ -339,7 +319,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
             if Puppet[:debug]
                 puts detail.backtrace
             end
-            Puppet.err "Could not retrieve %ss: %s" % [args[:name], detail]
+            Puppet.err "Could not retrieve #{args[:name]}s: %s" % detail
         end
 
         # Now clean up after ourselves
@@ -360,6 +340,23 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
 
             files << resource[:path]
         end
+    ensure
+        # Clear all existing definitions.
+        Facter.clear
+
+        # Reload everything.
+        if Facter.respond_to? :loadfacts
+            Facter.loadfacts
+        elsif Facter.respond_to? :load
+            Facter.load
+        else
+            raise Puppet::Error,
+                "You must upgrade your version of Facter to use centralized facts"
+        end
+
+        # This loads all existing facts and any new ones.  We have to remove and
+        # reload because there's no way to unload specific facts.
+        loadfacts()
     end
 
     # Retrieve the plugins from the central server.  We only have to load the
@@ -390,13 +387,12 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
         Dir.entries(dir).find_all { |e| e =~ /\.rb$/ }.each do |file|
             fqfile = ::File.join(dir, file)
             begin
-                Puppet.info "Loading %s %s" % 
-                    [type, ::File.basename(file.sub(".rb",''))]
+                Puppet.info "Loading #{type} %s" % ::File.basename(file.sub(".rb",''))
                 Timeout::timeout(self.timeout) do
                     load fqfile
                 end
             rescue => detail
-                Puppet.warning "Could not load %s %s: %s" % [type, fqfile, detail]
+                Puppet.warning "Could not load #{type} %s: %s" % [fqfile, detail]
             end
         end
     end
@@ -449,7 +445,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
         benchmark(:debug, "Retrieved catalog") do
             # error handling for this is done in the network client
             begin
-                textobjects = @driver.getconfig(textfacts, Puppet[:catalog_format])
+                textobjects = @driver.getconfig(textfacts, "yaml")
                 begin
                     textobjects = CGI.unescape(textobjects)
                 rescue => detail
@@ -479,19 +475,20 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
         @lockfile
     end
 
-    def splayed?
-        @splayed
-    end
-
     # Sleep when splay is enabled; else just return.
     def splay
         return unless Puppet[:splay]
-        return if splayed?
 
-        time = rand(Integer(Puppet[:splaylimit]))
+        limit = Integer(Puppet[:splaylimit])
+
+        # Pick a splay time and then cache it.
+        unless time = Puppet::Util::Storage.cache(:configuration)[:splay_time]
+            time = rand(limit)
+            Puppet::Util::Storage.cache(:configuration)[:splay_time] = time
+        end
+
         Puppet.info "Sleeping for %s seconds (splay is enabled)" % time
         sleep(time)
-        @splayed = true
     end
 
     private
diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb
index 815d0ba..3e62cdb 100755
--- a/lib/puppet/network/handler/fileserver.rb
+++ b/lib/puppet/network/handler/fileserver.rb
@@ -70,9 +70,7 @@ class Puppet::Network::Handler
             mount.debug("Describing %s for %s" % [url, client]) if client
 
             # use the mount to resolve the path for us.
-            return "" unless full_path = mount.file_path(path, client)
-
-            metadata = Puppet::FileServing::Metadata.new(url, :path => full_path, :links => links)
+            metadata = Puppet::FileServing::Metadata.new(url, :path => mount.file_path(path, client), :links => links)
 
             return "" unless metadata.exist?
 
@@ -653,38 +651,55 @@ class Puppet::Network::Handler
             # and "bad batch".
             #
             def list(relpath, recurse, ignore, client = nil)
-                abspath = file_path(relpath, client)
-                if FileTest.exists?(abspath)
-                    if FileTest.directory?(abspath) and recurse
-                        return reclist(abspath, recurse, ignore)
-                    else
-                        return [["/", File.stat(abspath).ftype]]
-                    end
-                end
-                return nil
+                reclist(file_path(relpath, client), nil, recurse, ignore)
             end
 
-            def reclist(abspath, recurse, ignore)
-                require 'puppet/file_serving'
-                require 'puppet/file_serving/fileset'
-                args = { :recurse => recurse, :links => :follow }
-                args[:ignore] = ignore if ignore
-                fs = Puppet::FileServing::Fileset.new(abspath, args)
-                ary = fs.files.collect do |file|
-                    if file == "."
-                        file = "/"
-                    else
-                        file = File.join("/", file )
+            # Recursively list the files in this tree.
+            def reclist(basepath, abspath, recurse, ignore)
+                abspath = basepath if abspath.nil?
+                relpath = abspath.sub(%r{^#{basepath}}, '')
+                relpath = "/#{relpath}" if relpath[0] != ?/  #/
+                
+                return unless FileTest.exists?(abspath)
+                
+                desc = [relpath]
+                
+                ftype = File.stat(abspath).ftype
+
+                desc << ftype
+                if recurse.is_a?(Integer)
+                    recurse -= 1
+                end
+
+                ary = [desc]
+                if recurse == true or (recurse.is_a?(Integer) and recurse > -1)
+                    if ftype == "directory"
+                        children = Dir.entries(abspath)
+                        if ignore
+                            children = handleignore(children, abspath, ignore)
+                        end  
+                        children.each { |child|
+                            next if child =~ /^\.\.?$/
+                            reclist(basepath, File.join(abspath, child), recurse, ignore).each { |cobj|
+                                ary << cobj
+                            }
+                        }
                     end
-                    stat = fs.stat(File.join(abspath, file))
-                    next if stat.nil?
-                    [ file, stat.ftype ]
                 end
 
                 return ary.compact
             end
 
-        end
+            # Deal with ignore parameters.
+            def handleignore(files, path, ignore_patterns)
+                ignore_patterns.each do |ignore|
+                    files.delete_if do |entry|
+                        File.fnmatch(ignore, entry, File::FNM_DOTMATCH)
+                    end
+                end
+                return files
+            end
+        end  
 
         # A special mount class specifically for the plugins mount -- just
         # has some magic to effectively do a union mount of the 'plugins'
@@ -712,7 +727,7 @@ class Puppet::Network::Handler
             end
             
             def file_path(relpath, client = nil)
-                return nil unless mod = valid_modules.map { |m| mod_path_exists?(m, relpath, client) ? m : nil }.compact.first
+                mod = valid_modules.map { |m| mod_path_exists?(m, relpath, client) ? m : nil }.compact.first
                 mod_file_path(mod, relpath, client)
             end
 
@@ -720,16 +735,9 @@ class Puppet::Network::Handler
             def list(relpath, recurse, ignore, client = nil)
                 result = []
                 valid_modules.each do |m|
-                    modpath = mod_file_path(m, relpath, client)
-                    if FileTest.exists?(modpath)
-                        if FileTest.directory?(modpath) and recurse
-                            ary = reclist(modpath, recurse, ignore)
-                            ary = [] if ary.nil?
-                            result += ary
-                        else
-                            result += [["/", File.stat(modpath).ftype]]
-                        end
-                    end
+                    ary = reclist(mod_file_path(m, relpath, client), nil, recurse, ignore)
+                    ary = [] if ary.nil?
+                   result += ary
                 end
                 result
             end
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index 71b633a..851ccc7 100644
--- a/lib/puppet/network/handler/master.rb
+++ b/lib/puppet/network/handler/master.rb
@@ -24,7 +24,7 @@ class Puppet::Network::Handler
         # Tell a client whether there's a fresh config for it
         def freshness(client = nil, clientip = nil)
             # Always force a recompile.  Newer clients shouldn't do this (as of April 2008).
-            return Time.now.to_i
+            Time.now
         end
 
         def initialize(hash = {})
@@ -56,22 +56,35 @@ class Puppet::Network::Handler
         # Call our various handlers; this handler is getting deprecated.
         def getconfig(facts, format = "marshal", client = nil, clientip = nil)
             facts = decode_facts(facts)
-
-            client ||= facts["hostname"]
+            client, clientip = clientname(client, clientip, facts)
 
             # Pass the facts to the fact handler
             Puppet::Node::Facts.new(client, facts).save unless local?
 
             catalog = Puppet::Node::Catalog.find(client)
 
-            case format
-            when "yaml":
-                return CGI.escape(catalog.extract.to_yaml(:UseBlock => true))
-            when "marshal":
-                return CGI.escape(Marshal.dump(catalog.extract))
-            else
-                raise "Invalid markup format '%s'" % format
+            return translate(catalog.extract)
+        end
+
+        private
+
+        # Manipulate the client name as appropriate.
+        def clientname(name, ip, facts)
+            # Always use the hostname from Facter.
+            client = facts["hostname"]
+            clientip = facts["ipaddress"]
+            if Puppet[:node_name] == 'cert'
+                if name
+                    client = name
+                    facts["fqdn"] = client
+                    facts["hostname"], facts["domain"] = client.split('.', 2)
+                end
+                if ip
+                    clientip = ip
+                end
             end
+
+            return client, clientip
         end
 
         # 
@@ -97,6 +110,11 @@ class Puppet::Network::Handler
 
         # Translate our configuration appropriately for sending back to a client.
         def translate(config)
+            if local?
+                config
+            else
+                CGI.escape(config.to_yaml(:UseBlock => true))
+            end
         end
     end
 end
diff --git a/lib/puppet/network/http.rb b/lib/puppet/network/http.rb
index c219859..062c67c 100644
--- a/lib/puppet/network/http.rb
+++ b/lib/puppet/network/http.rb
@@ -1,15 +1,13 @@
 class Puppet::Network::HTTP
     def self.server_class_by_type(kind)
-        case kind.to_sym
-        when :webrick:
-            require 'puppet/network/http/webrick'
-            return Puppet::Network::HTTP::WEBrick
-        when :mongrel:
+        return Puppet::Network::HTTP::WEBrick if kind.to_sym == :webrick
+        if kind.to_sym == :mongrel
             raise ArgumentError, "Mongrel is not installed on this platform" unless Puppet.features.mongrel?
-            require 'puppet/network/http/mongrel'
             return Puppet::Network::HTTP::Mongrel 
-        else
-            raise ArgumentError, "Unknown HTTP server name [#{kind}]"
         end
+        raise ArgumentError, "Unknown HTTP server name [#{kind}]"
     end
 end
+
+require 'puppet/network/http/webrick'
+require 'puppet/network/http/mongrel'
diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb
index 3c14c8a..7113c92 100644
--- a/lib/puppet/network/http/handler.rb
+++ b/lib/puppet/network/http/handler.rb
@@ -1,30 +1,30 @@
 module Puppet::Network::HTTP::Handler
-
+    
     def initialize_for_puppet(args = {})
         raise ArgumentError unless @server = args[:server]
         raise ArgumentError unless @handler = args[:handler]
         @model = find_model_for_handler(@handler)
     end
-
+    
     # handle an HTTP request
     def process(request, response)
         return do_find(request, response)       if get?(request)    and singular?(request)
         return do_search(request, response)     if get?(request)    and plural?(request)
         return do_destroy(request, response)    if delete?(request) and singular?(request)
-        return do_save(request, response)       if put?(request)    and singular?(request)
+        return do_save(request, response)       if put?(request) and singular?(request)
         raise ArgumentError, "Did not understand HTTP #{http_method(request)} request for '#{path(request)}'"
     rescue Exception => e
         return do_exception(request, response, e)
     end
-
+    
   private
 
     def model
-        @model
+      @model
     end
-
+    
     def do_find(request, response)
-        key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path(request)}]")
+        key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]")
         args = params(request)
         result = model.find(key, args).to_yaml
         encode_result(request, response, result)
@@ -37,7 +37,7 @@ module Puppet::Network::HTTP::Handler
     end
 
     def do_destroy(request, response)
-        key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path(request)}]")
+        key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]")
         args = params(request)
         result = model.destroy(key, args)
         encode_result(request, response, YAML.dump(result))
@@ -46,73 +46,71 @@ module Puppet::Network::HTTP::Handler
     def do_save(request, response)
         data = body(request).to_s
         raise ArgumentError, "No data to save" if !data or data.empty?
-        args = params(request)
+        # args = params(request)
         obj = model.from_yaml(data)
-        result = save_object(obj, args).to_yaml
+        result = save_object(obj).to_yaml
         encode_result(request, response, result)
     end
-
-    # LAK:NOTE This has to be here for testing; it's a stub-point so
-    # we keep infinite recursion from happening.
-    def save_object(object, args)
-        object.save(args)
+    
+    def save_object(obj)
+      obj.save
     end
-
+  
     def do_exception(request, response, exception, status=404)
         encode_result(request, response, exception.to_yaml, status)
     end
-
+  
     def find_model_for_handler(handler)
         Puppet::Indirector::Indirection.model(handler) || 
             raise(ArgumentError, "Cannot locate indirection [#{handler}].")
     end
-
+    
     def get?(request)
         http_method(request) == 'GET'
     end
-
+    
     def put?(request)
         http_method(request) == 'PUT'
     end
-
+    
     def delete?(request)
         http_method(request) == 'DELETE'
     end
-
+    
     def singular?(request)
         %r{/#{@handler.to_s}$}.match(path(request))
     end
-
+    
     def plural?(request)
         %r{/#{@handler.to_s}s$}.match(path(request))
     end
-
-    # methods to be overridden by the including web server class
-
+    
+  # methods to be overridden by the including web server class
+    
     def register_handler
         raise NotImplementedError
     end
-
+    
     def http_method(request)
         raise NotImplementedError
     end
-
+    
     def path(request)
         raise NotImplementedError
     end    
-
+    
     def request_key(request)
         raise NotImplementedError
     end
-
+    
     def body(request)
         raise NotImplementedError
     end
-
+    
     def params(request)
         raise NotImplementedError
     end
-
+    
     def encode_result(request, response, result, status = 200)
         raise NotImplementedError
     end
diff --git a/lib/puppet/network/http/mongrel/rest.rb b/lib/puppet/network/http/mongrel/rest.rb
index 520ad67..2a3d4f1 100644
--- a/lib/puppet/network/http/mongrel/rest.rb
+++ b/lib/puppet/network/http/mongrel/rest.rb
@@ -2,65 +2,46 @@ require 'puppet/network/http/handler'
 
 class Puppet::Network::HTTP::MongrelREST < Mongrel::HttpHandler
 
-    include Puppet::Network::HTTP::Handler
-
-    def initialize(args={})
-        super()
-        initialize_for_puppet(args)
-    end
-
-    # Return the query params for this request.  We had to expose this method for
-    # testing purposes.
-    def params(request)
-        Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"]).merge(client_info(request))
-    end
+  include Puppet::Network::HTTP::Handler
+  
+  def initialize(args={})
+    super()
+    initialize_for_puppet(args)
+  end
 
   private
-
+ 
     # which HTTP verb was used in this request
     def http_method(request)
         request.params[Mongrel::Const::REQUEST_METHOD]
     end
-
+    
     # what path was requested?
     def path(request)
         # LAK:NOTE See http://snurl.com/21zf8  [groups_google_com] 
         x = '/' + request.params[Mongrel::Const::REQUEST_PATH].split('/')[1]
     end
-
+    
     # return the key included in the request path
     def request_key(request)
         # LAK:NOTE See http://snurl.com/21zf8  [groups_google_com] 
         x = request.params[Mongrel::Const::REQUEST_PATH].split('/')[2]        
     end
-
+    
     # return the request body
     def body(request)
         request.body
     end
-
+    
+    # return the query params for this request
+    def params(request)
+        Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"])
+    end
+    
     # produce the body of the response
     def encode_result(request, response, result, status = 200)
         response.start(status) do |head, body|
             body.write(result)
         end
     end
-
-    def client_info(request)
-        result = {}
-        params = request.params
-        result[:ip] = params["REMOTE_ADDR"]
-
-        # JJM #906 The following dn.match regular expression is forgiving
-        # enough to match the two Distinguished Name string contents
-        # coming from Apache, Pound or other reverse SSL proxies.
-        if dn = params[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
-            result[:node] = dn_matchdata[1].to_str
-            result[:authenticated] = (params[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
-        else
-            result[:authenticated] = false
-        end
-
-        return result
-    end
 end
diff --git a/lib/puppet/network/http/webrick/rest.rb b/lib/puppet/network/http/webrick/rest.rb
index a235fb4..b439121 100644
--- a/lib/puppet/network/http/webrick/rest.rb
+++ b/lib/puppet/network/http/webrick/rest.rb
@@ -1,67 +1,46 @@
 require 'puppet/network/http/handler'
 
 class Puppet::Network::HTTP::WEBrickREST < WEBrick::HTTPServlet::AbstractServlet
-
+  
     include Puppet::Network::HTTP::Handler
-
+    
     def initialize(server, handler)
-        raise ArgumentError, "server is required" unless server
-        super(server)
-        initialize_for_puppet(:server => server, :handler => handler)
-    end
-
-    # We had to expose this method for testing purposes.
-    def params(request)
-        result = request.query
-        result.merge(client_information(request))
+      raise ArgumentError, "server is required" unless server
+      super(server)
+      initialize_for_puppet(:server => server, :handler => handler)
     end
 
     # WEBrick uses a service() method to respond to requests.  Simply delegate to the handler response() method.
     def service(request, response)
         process(request, response)
     end
-
+    
   private
-
+    
     def http_method(request)
         request.request_method
     end
-
+    
     def path(request)
         # LAK:NOTE See http://snurl.com/21zf8  [groups_google_com] 
         x = '/' + request.path.split('/')[1]
     end
-
+    
     def request_key(request)
         # LAK:NOTE See http://snurl.com/21zf8  [groups_google_com] 
         x = request.path.split('/')[2]
     end
-
+    
     def body(request)
         request.body
     end
-
+    
+    def params(request)
+        request.query
+    end
+    
     def encode_result(request, response, result, status = 200)
         response.status = status
         response.body = result
     end
-
-    # Retrieve node/cert/ip information from the request object.
-    def client_information(request)
-        result = {}
-        if peer = request.peeraddr and ip = peer[3]
-            result[:ip] = ip
-        end
-
-        # If they have a certificate (which will almost always be true)
-        # then we get the hostname from the cert, instead of via IP
-        # info
-        result[:authenticated] = false
-        if cert = request.client_cert and nameary = cert.subject.to_a.find { |ary| ary[0] == "CN" }
-            result[:node] = nameary[1]
-            result[:authenticated] = true
-        end
-
-        result
-    end
 end
diff --git a/lib/puppet/network/http_pool.rb b/lib/puppet/network/http_pool.rb
index 1227f78..9d37f2e 100644
--- a/lib/puppet/network/http_pool.rb
+++ b/lib/puppet/network/http_pool.rb
@@ -88,9 +88,8 @@ module Puppet::Network::HttpPool
         class << http; attr_accessor :ca_file; end
 
         http.use_ssl = true
-        # Use configured timeout (#1176)
-        http.read_timeout = Puppet[:configtimeout]
-        http.open_timeout = Puppet[:configtimeout]
+        http.read_timeout = 120
+        http.open_timeout = 120
         # JJM Configurable fix for #896.
         if Puppet[:http_enable_post_connection_check]
             http.enable_post_connection_check = true
diff --git a/lib/puppet/network/http_server/rack.rb b/lib/puppet/network/http_server/rack.rb
deleted file mode 100644
index 806007a..0000000
--- a/lib/puppet/network/http_server/rack.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-# Author: Christian Hofstaedtler <hofstaedtler at inqnet.at>
-# Copyright (c) 2006 Manuel Holtgrewe, 2007 Luke Kanies,
-#               2008 Christian Hofstaedtler
-#
-# This file is mostly based on the mongrel module, which is part of
-# the standard puppet distribution.
-#
-# puppet/network/http_server/mongrel.rb has the following license, 
-# and is based heavily on a file retrieved from:
-# http://ttt.ggnore.net/2006/11/15/xmlrpc-with-mongrel-and-ruby-off-rails/
-#
-# 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.
-
-
-require 'puppet'
-require 'puppet/network/handler'
-require 'puppet/sslcertificates'
-
-require 'xmlrpc/server'
-require 'puppet/network/xmlrpc/server'
-require 'puppet/network/http_server'
-require 'puppet/network/client_request'
-require 'puppet/network/handler'
-
-require 'resolv'
-require 'rack'
-
-# A handler for a Rack-style puppet(master)d. For the most part, it works 
-# exactly the same as HTTPServer::Mongrel:
-# After checking whether the request itself is sane, the handler forwards 
-# it to an internal instance of XMLRPC::BasicServer to process it.
-module Puppet::Network
-	class HTTPServer::Rack
-		attr_reader :xmlrpc_server
-
-		def initialize(handlers)
-			@debug = false
-			if Puppet[:debug]
-				@debug = true
-			end
-
-			Puppet.info "Starting Rack server for puppet version %s" % Puppet.version
-			if Puppet[:name] != "puppetmasterd" then
-				Puppet.warn 'Rack server is not named "puppetmasterd", this may be not what you want. ($0 = %s)' % $0
-			end
-
-			@xmlrpc_server = Puppet::Network::XMLRPCServer.new
-			handlers.each do |name, args|
-				unless handler = Puppet::Network::Handler.handler(name)
-					raise ArgumentError, "Invalid handler %s" % name
-				end
-				h = handler.new(args)
-				@xmlrpc_server.add_handler(handler.interface, h)
-			end
-			Puppet.info "Rack server is waiting to serve requests."
-		end
-
-		# Validate a rack-style request (in env), and run the requested XMLRPC
-		# call.
-		def process(env)
-			# time to serve a request
-			req = Rack::Request.new(env)
-
-			if @debug then
-				Puppet.info "Handling request, details:"
-				env.each do |name, val|
-					l = "  env: %s ->" % name
-					l = l + ' %s' % val
-					Puppet.info l
-				end
-			end
-
-			if not req.post? then
-				return [405, { "Content-Type" => "text/html" }, "Method Not Allowed"]
-			end
-			if req.media_type() != "text/xml" then
-				return [400, { "Content-Type" => "text/html" }, "Bad Request"]
-			end
-			if req.content_length().to_i <= 0 then
-				return [411, { "Content-Type" => "text/html" }, "Length Required"]
-			end
-
-			body = ''
-			req.body().each { |line| body = body + line }
-			if @debug then
-				Puppet.info "Request Body: %s" % body
-			end
-			if body.size != req.content_length().to_i then
-				if @debug then
-					Puppet.info "body length didnt match %d" % body.size
-					Puppet.info " vs. -> %d" % req.content_length().to_i
-				end
-				return [400, { "Content-Type" => "text/html" }, "Bad Request Length"]
-			end
-			info = client_info(env)
-			begin
-				data = @xmlrpc_server.process(body, info)
-				return [200, { "Content-Type" => "text/xml; charset=utf-8" }, data]
-			rescue => detail
-				Puppet.err "Rack: Internal Server Error: XMLRPC_Server.process problem. Details follow: "
-				detail.backtrace.each { |line| 	Puppet.err " --> %s" % line }
-				return [500, { "Content-Type" => "text/html" }, "Internal Server Error"]
-			end
-		end
-
-		private
-
-		def client_info(request)
-			ip = request["REMOTE_ADDR"]
-			# JJM #906 The following dn.match regular expression is forgiving
-			# enough to match the two Distinguished Name string contents
-			# coming from Apache, Pound or other reverse SSL proxies.
-			if dn = request[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
-				client = dn_matchdata[1].to_str
-				valid = (request[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
-			else
-				begin
-					client = Resolv.getname(ip)
-				rescue => detail
-					Puppet.err "Could not resolve %s: %s" % [ip, detail]
-					client = "unknown"
-				end
-				valid = false
-			end
-			info = Puppet::Network::ClientRequest.new(client, ip, valid)
-			return info
-		end
-	end
-end
-
diff --git a/lib/puppet/network/xmlrpc/client.rb b/lib/puppet/network/xmlrpc/client.rb
index c79f91d..357a766 100644
--- a/lib/puppet/network/xmlrpc/client.rb
+++ b/lib/puppet/network/xmlrpc/client.rb
@@ -35,6 +35,10 @@ module Puppet::Network
 
             interface.methods.each { |ary|
                 method = ary[0]
+                if public_method_defined?(method)
+                    raise Puppet::DevError, "Method %s is already defined" %
+                        method
+                end
                 newclient.send(:define_method,method) { |*args|
                     Puppet.debug "Calling %s.%s" % [namespace, method]
                     begin
@@ -47,7 +51,7 @@ module Puppet::Network
                         end
                         ["certificate verify failed", "hostname was not match", "hostname not match"].each do |str|
                             if detail.message.include?(str)
-                                Puppet.warning "Certificate validation failed; consider using the certname configuration option"
+                                Puppet.warning "Certificate validation failed; considering using the certname configuration option"
                             end
                         end 
                         raise XMLRPCClientError,
@@ -70,10 +74,6 @@ module Puppet::Network
                         Puppet.warning "Other end went away; restarting connection and retrying"
                         self.recycle_connection
                         retry
-                    rescue Timeout::Error => detail
-                        Puppet.err "Connection timeout calling %s.%s: %s" %
-                            [namespace, method, detail.to_s]
-                        raise XMLRPCClientError.new("Connection Timeout").set_backtrace(detail.backtrace)
                     rescue => detail
                         if detail.message =~ /^Wrong size\. Was \d+, should be \d+$/
                             Puppet.warning "XMLRPC returned wrong size.  Retrying."
@@ -123,7 +123,7 @@ module Puppet::Network
                 nil, # user
                 nil, # password
                 true, # use_ssl
-                Puppet[:configtimeout] # use configured timeout (#1176)
+                120 # a two minute timeout, instead of 30 seconds
             )
             @http = Puppet::Network::HttpPool.http_instance(@host, @port)
         end
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index e10299d..c0628ec 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -13,9 +13,92 @@ class Puppet::Node
     indirects :node, :terminus_setting => :node_terminus, :doc => "Where to find node information.
         A node is composed of its name, its facts, and its environment."
 
-    attr_accessor :name, :classes, :parameters, :source, :ipaddress
+    # Retrieve a node from the node source, with some additional munging
+    # thrown in for kicks.
+    def self.find_by_any_name(key)
+        return nil unless key
+
+        facts = node_facts(key)
+        node = nil
+        names = node_names(key, facts)
+        names.each do |name|
+            name = name.to_s if name.is_a?(Symbol)
+            break if node = find(name)
+        end
+
+        # If they made it this far, we haven't found anything, so look for a
+        # default node.
+        unless node or names.include?("default")
+            if node = find("default")
+                Puppet.notice "Using default node for %s" % key
+            end
+        end
+
+        if node
+            node.names = names
+
+            return node
+        else
+            return nil
+        end
+    end
+
+    private
+
+    # Look up the node facts so we can generate the node names to use.
+    def self.node_facts(key)
+        if facts = Puppet::Node::Facts.find(key)
+            facts.values
+        else
+            {}
+        end
+    end
+
+    # Calculate the list of node names we should use for looking
+    # up our node.
+    def self.node_names(key, facts = nil)
+        facts ||= node_facts(key)
+        names = []
+
+        if hostname = facts["hostname"]
+            unless hostname == key
+                names << hostname
+            end
+        else
+            hostname = key
+        end
+
+        if fqdn = facts["fqdn"]
+            hostname = fqdn
+            names << fqdn
+        end
+
+        # Make sure both the fqdn and the short name of the
+        # host can be used in the manifest
+        if hostname =~ /\./
+            names << hostname.sub(/\..+/,'')
+        elsif domain = facts['domain']
+            names << hostname + "." + domain
+        end
+
+        # Sort the names inversely by name length.
+        names.sort! { |a,b| b.length <=> a.length }
+
+        # And make sure the key is first, since that's the most
+        # likely usage.
+        ([key] + names).uniq
+    end
+
+    public
+
+    attr_accessor :name, :classes, :parameters, :source, :ipaddress, :names
     attr_reader :time
-    attr_writer :environment
+
+    # Set the environment, making sure that it's valid.
+    def environment=(value)
+        raise(ArgumentError, "Invalid environment %s" % value) unless Puppet::Node::Environment.valid?(value)
+        @environment = value
+    end
 
     # Do not return environments that are the empty string, and use
     # explicitly set environments, then facts, then a central env
@@ -23,6 +106,7 @@ class Puppet::Node
     def environment
         unless @environment
             if env = parameters["environment"]
+                raise(ArgumentError, "Invalid environment %s from parameters" % env) unless Puppet::Node::Environment.valid?(env)
                 @environment = env
             else
                 @environment = Puppet::Node::Environment.new.name.to_s
@@ -69,8 +153,6 @@ class Puppet::Node
     def fact_merge
         if facts = Puppet::Node::Facts.find(name)
             merge(facts.values)
-        else
-            Puppet.warning "Could not find facts for %s; you probably have a discrepancy between the node and fact names" % name
         end
     end
 
@@ -80,41 +162,4 @@ class Puppet::Node
             @parameters[name] = value unless @parameters.include?(name)
         end
     end
-
-    # Calculate the list of names we might use for looking
-    # up our node.  This is only used for AST nodes.
-    def names
-        names = []
-
-        # First, get the fqdn
-        unless fqdn = parameters["fqdn"]
-            if parameters["hostname"] and parameters["domain"]
-                 fqdn = parameters["hostname"] + "." + parameters["domain"]
-            else
-                 Puppet.warning "Host is missing hostname and/or domain: %s" % name
-            end
-        end
-
-        # Now that we (might) have the fqdn, add each piece to the name
-        # list to search, in order of longest to shortest.
-        if fqdn
-            list = fqdn.split(".")
-            tmp = []
-            list.each_with_index do |short, i|
-                tmp << list[0..i].join(".")
-            end
-            names += tmp.reverse
-        end
-
-        # And make sure the node name is first, since that's the most
-        # likely usage.
-        #   The name is usually the Certificate CN, but it can be
-        # set to the 'facter' hostname instead.
-        if Puppet[:node_name] == 'cert'
-            names.unshift name
-        else
-            names.unshift parameters["hostname"]
-        end
-        names.uniq
-    end
 end
diff --git a/lib/puppet/node/catalog.rb b/lib/puppet/node/catalog.rb
index 1792738..ecda472 100644
--- a/lib/puppet/node/catalog.rb
+++ b/lib/puppet/node/catalog.rb
@@ -88,12 +88,6 @@ class Puppet::Node::Catalog < Puppet::PGraph
         resource.ref =~ /^(.+)\[/
 
         newref = "%s[%s]" % [$1 || resource.class.name, name]
-
-        # LAK:NOTE It's important that we directly compare the references,
-        # because sometimes an alias is created before the resource is
-        # added to the catalog, so comparing inside the below if block
-        # isn't sufficient.
-        return if newref == resource.ref
         if existing = @resource_table[newref]
             return if existing == resource
             raise(ArgumentError, "Cannot alias %s to %s; resource %s already exists" % [resource.ref, name, newref])
@@ -489,9 +483,6 @@ class Puppet::Node::Catalog < Puppet::PGraph
             if resource.is_a?(Puppet::TransObject)
                 resource = resource.dup
                 resource.catalog = result
-            elsif resource.is_a?(Puppet::Parser::Resource)
-                resource = resource.to_transobject
-                resource.catalog = result
             end
 
             newres = resource.send(convert)
diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb
index b64b9c2..343720a 100644
--- a/lib/puppet/node/environment.rb
+++ b/lib/puppet/node/environment.rb
@@ -1,14 +1,30 @@
 # Model the environment that a node can operate in.  This class just
 # provides a simple wrapper for the functionality around environments.
 class Puppet::Node::Environment
+    # Return the list of valid environments.  Just looks them up in
+    # the settings.
+    def self.valid
+        # LAK:NOTE See http://snurl.com/21zf8  [groups_google_com] 
+        x = Puppet.settings.value(:environments).split(",").collect { |e| e.to_sym }
+    end
+
+    # Is the provided environment valid?
+    def self.valid?(name)
+        return false if name.to_s == ""
+        valid.include?(name.to_sym)
+    end
+
     @seen = {}
 
-    # Return an existing environment instance, or create a new one.
+    # Return an existing environment instance, or create a new one,
+    # validating the environment name.
     def self.new(name = nil)
         name ||= Puppet.settings.value(:environment)
 
         raise ArgumentError, "Environment name must be specified" unless name
 
+        raise(ArgumentError, "'%s' is not a valid environment" % name) unless valid?(name)
+
         symbol = name.to_sym
 
         return @seen[symbol] if @seen[symbol]
diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb
index f90193f..31e009a 100644
--- a/lib/puppet/parameter.rb
+++ b/lib/puppet/parameter.rb
@@ -413,12 +413,39 @@ class Puppet::Parameter
         @shadow = nil
     end
 
-    attr_reader :value
+    # This should only be called for parameters, but go ahead and make
+    # it possible to call for properties, too.
+    def value
+        if self.is_a?(Puppet::Property)
+            # We should return the 'is' value if there's not 'should'
+            # value.  This might be bad, though, because the 'should'
+            # method knows whether to return an array or not and that info
+            # is not exposed, and the 'is' value could be a symbol.  I
+            # can't seem to create a test in which this is a problem, but
+            # that doesn't mean it's not one.
+            if self.should
+                return self.should
+            else
+                return self.retrieve
+            end
+        else
+            if defined? @value
+                return @value
+            else
+                return nil
+            end
+        end
+    end
 
     # Store the value provided.  All of the checking should possibly be
     # late-binding (e.g., users might not exist when the value is assigned
     # but might when it is asked for).
     def value=(value)
+        # If we're a parameter, just hand the processing off to the should
+        # method.
+        if self.is_a?(Puppet::Property)
+            return self.should = value
+        end
         if respond_to?(:validate)
             validate(value)
         end
diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index ddf8852..c9bd7c9 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -74,25 +74,19 @@ class Puppet::Parser::AST
 end
 
 # And include all of the AST subclasses.
-require 'puppet/parser/ast/arithmetic_operator'
 require 'puppet/parser/ast/astarray'
 require 'puppet/parser/ast/branch'
-require 'puppet/parser/ast/boolean_operator'
 require 'puppet/parser/ast/caseopt'
 require 'puppet/parser/ast/casestatement'
 require 'puppet/parser/ast/collection'
 require 'puppet/parser/ast/collexpr'
-require 'puppet/parser/ast/comparison_operator'
 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/minus'
 require 'puppet/parser/ast/node'
-require 'puppet/parser/ast/nop'
-require 'puppet/parser/ast/not'
 require 'puppet/parser/ast/resource'
 require 'puppet/parser/ast/resource_defaults'
 require 'puppet/parser/ast/resource_override'
diff --git a/lib/puppet/parser/ast/arithmetic_operator.rb b/lib/puppet/parser/ast/arithmetic_operator.rb
deleted file mode 100644
index 8d9cef8..0000000
--- a/lib/puppet/parser/ast/arithmetic_operator.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require 'puppet'
-require 'puppet/parser/ast/branch'
-
-class Puppet::Parser::AST
-    class ArithmeticOperator < AST::Branch
-
-        attr_accessor :operator, :lval, :rval
-
-        # Iterate across all of our children.
-        def each
-            [@lval, at rval, at operator].each { |child| yield child }
-        end
-
-        # Returns a boolean which is the result of the boolean operation
-        # of lval and rval operands
-        def evaluate(scope)
-            # evaluate the operands, should return a boolean value
-            lval = @lval.safeevaluate(scope)
-            lval = Puppet::Parser::Scope.number?(lval)
-            if lval == nil
-                raise ArgumentError, "left operand of %s is not a number" % @operator
-            end
-            rval = @rval.safeevaluate(scope)
-            rval = Puppet::Parser::Scope.number?(rval)
-            if rval == nil
-                raise ArgumentError, "right operand of %s is not a number" % @operator
-            end
-
-            # compute result
-            lval.send(@operator, rval)
-        end
-
-        def initialize(hash)
-            super
-
-            unless %w{+ - * / << >>}.include?(@operator)
-                raise ArgumentError, "Invalid arithmetic operator %s" % @operator
-            end
-        end
-    end
-end
diff --git a/lib/puppet/parser/ast/boolean_operator.rb b/lib/puppet/parser/ast/boolean_operator.rb
deleted file mode 100644
index c3b5c7d..0000000
--- a/lib/puppet/parser/ast/boolean_operator.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require 'puppet'
-require 'puppet/parser/ast/branch'
-
-class Puppet::Parser::AST
-    class BooleanOperator < AST::Branch
-
-        attr_accessor :operator, :lval, :rval
-
-        # Iterate across all of our children.
-        def each
-            [@lval, at rval, at operator].each { |child| yield child }
-        end
-
-        # Returns a boolean which is the result of the boolean operation
-        # of lval and rval operands
-        def evaluate(scope)
-            # evaluate the first operand, should return a boolean value
-            lval = @lval.safeevaluate(scope)
-            
-            # return result
-            # lazy evaluate right operand
-            case @operator
-            when "and";
-                if Puppet::Parser::Scope.true?(lval)
-                    rval = @rval.safeevaluate(scope)
-                    Puppet::Parser::Scope.true?(rval)
-                else # false and false == false
-                    false
-                end
-            when "or"; 
-                if Puppet::Parser::Scope.true?(lval) 
-                    true
-                else
-                    rval = @rval.safeevaluate(scope)
-                    Puppet::Parser::Scope.true?(rval)
-                end
-            end
-        end
-
-        def initialize(hash)
-            super
-
-            unless %w{and or}.include?(@operator)
-                raise ArgumentError, "Invalid boolean operator %s" % @operator
-            end
-        end
-    end
-end
diff --git a/lib/puppet/parser/ast/collexpr.rb b/lib/puppet/parser/ast/collexpr.rb
index baed325..3e13d94 100644
--- a/lib/puppet/parser/ast/collexpr.rb
+++ b/lib/puppet/parser/ast/collexpr.rb
@@ -30,12 +30,7 @@ class CollExpr < AST::Branch
             case @oper
             when "and": code1.call(resource) and code2.call(resource)
             when "or": code1.call(resource) or code2.call(resource)
-            when "==":
-                if resource[str1].is_a?(Array) && form != :exported
-                    resource[str1].include?(str2)
-                else
-                    resource[str1] == str2
-                end
+            when "==": resource[str1] == str2
             when "!=": resource[str1] != str2
             end
         end
diff --git a/lib/puppet/parser/ast/comparison_operator.rb b/lib/puppet/parser/ast/comparison_operator.rb
deleted file mode 100644
index 63aa36c..0000000
--- a/lib/puppet/parser/ast/comparison_operator.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'puppet'
-require 'puppet/parser/ast/branch'
-
-class Puppet::Parser::AST
-    class ComparisonOperator < AST::Branch
-
-        attr_accessor :operator, :lval, :rval
-
-        # Iterate across all of our children.
-        def each
-            [@lval, at rval, at operator].each { |child| yield child }
-        end
-
-        # Returns a boolean which is the result of the boolean operation
-        # of lval and rval operands
-        def evaluate(scope)
-            # evaluate the operands, should return a boolean value
-            lval = @lval.safeevaluate(scope)
-            rval = @rval.safeevaluate(scope)
-
-            # return result
-            unless @operator == '!='
-                lval.send(@operator,rval)
-            else
-                lval != rval
-            end
-        end
-
-        def initialize(hash)
-            super
-
-            unless %w{== != < > <= >=}.include?(@operator)
-                raise ArgumentError, "Invalid comparison operator %s" % @operator
-            end
-        end
-    end
-end
diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb
index eb36fa9..63d7c7a 100644
--- a/lib/puppet/parser/ast/function.rb
+++ b/lib/puppet/parser/ast/function.rb
@@ -42,7 +42,7 @@ class Puppet::Parser::AST
                 raise Puppet::DevError, "Invalid function type %s" % @ftype.inspect
             end
 
-            # Lastly, check the parity
+            # Lastly, check the arity
         end
     end
 end
diff --git a/lib/puppet/parser/ast/minus.rb b/lib/puppet/parser/ast/minus.rb
deleted file mode 100644
index b0779a8..0000000
--- a/lib/puppet/parser/ast/minus.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require 'puppet'
-require 'puppet/parser/ast/branch'
-
-# An object that returns a boolean which is the boolean not
-# of the given value.
-class Puppet::Parser::AST
-    class Minus < AST::Branch
-        attr_accessor :value
-
-        def each
-            yield @value
-        end
-
-        def evaluate(scope)
-            val = @value.safeevaluate(scope)
-            val = Puppet::Parser::Scope.number?(val)
-            if val == nil
-                raise ArgumentError, "minus operand %s is not a number" % val
-            end
-            return -val
-        end
-    end
-end
diff --git a/lib/puppet/parser/ast/nop.rb b/lib/puppet/parser/ast/nop.rb
deleted file mode 100644
index ea52320..0000000
--- a/lib/puppet/parser/ast/nop.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require 'puppet/parser/ast/branch'
-
-class Puppet::Parser::AST
-    # This class is a no-op, it doesn't produce anything
-    # when evaluated, hence it's name :-)
-    class Nop < AST::Leaf
-        def evaluate(scope)
-            # nothing to do
-        end
-    end
-end
diff --git a/lib/puppet/parser/ast/not.rb b/lib/puppet/parser/ast/not.rb
deleted file mode 100644
index c8fa1df..0000000
--- a/lib/puppet/parser/ast/not.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require 'puppet'
-require 'puppet/parser/ast/branch'
-
-# An object that returns a boolean which is the boolean not
-# of the given value.
-class Puppet::Parser::AST
-    class Not < AST::Branch
-        attr_accessor :value
-
-        def each
-            yield @value
-        end
-
-        def evaluate(scope)
-            val = @value.safeevaluate(scope)
-            return ! Puppet::Parser::Scope.true?(val)
-        end
-    end
-end
diff --git a/lib/puppet/parser/ast/resource_override.rb b/lib/puppet/parser/ast/resource_override.rb
index 8380dcd..f9464ac 100644
--- a/lib/puppet/parser/ast/resource_override.rb
+++ b/lib/puppet/parser/ast/resource_override.rb
@@ -19,7 +19,7 @@ class Puppet::Parser::AST
         # in the current scope.
         def evaluate(scope)
             # Get our object reference.
-            resource = @object.safeevaluate(scope)
+            object = @object.safeevaluate(scope)
 
             hash = {}
 
@@ -30,28 +30,21 @@ class Puppet::Parser::AST
 
             # Now we just create a normal resource, but we call a very different
             # method on the scope.
-            resource = [resource] unless resource.is_a?(Array)
-            
-            resource = resource.collect do |r|
-                res = Puppet::Parser::Resource.new(
-                    :type => r.type,
-                    :title => r.title,
-                    :params => params,
-                    :file => @file,
-                    :line => @line,
-                    :source => scope.source,
-                    :scope => scope
-                )
-
-                # Now we tell the scope that it's an override, and it behaves as
-                # necessary.
-                scope.compiler.add_override(res)
-
-                res
-            end
-            # decapsulate array in case of only one item
-            return resource.pop if resource.length == 1
-            return resource
+            obj = Puppet::Parser::Resource.new(
+                :type => object.type,
+                :title => object.title,
+                :params => params,
+                :file => @file,
+                :line => @line,
+                :source => scope.source,
+                :scope => scope
+            )
+
+            # Now we tell the scope that it's an override, and it behaves as
+            # necessary.
+            scope.compiler.add_override(obj)
+
+            obj
         end
 
         # Create our ResourceDef.  Handles type checking for us.
diff --git a/lib/puppet/parser/ast/resource_reference.rb b/lib/puppet/parser/ast/resource_reference.rb
index e5e2dce..4bb4116 100644
--- a/lib/puppet/parser/ast/resource_reference.rb
+++ b/lib/puppet/parser/ast/resource_reference.rb
@@ -24,20 +24,16 @@ class Puppet::Parser::AST
         # and name.
         def evaluate(scope)
             title = @title.safeevaluate(scope)
-            title = [title] unless title.is_a?(Array)
-            
             if @type.to_s.downcase == "class"
-                resource_type = "class"
-                title = title.collect { |t| qualified_class(scope, t) }
+                objtype = "class"
+                title = qualified_class(scope, title)
             else
-                resource_type = qualified_type(scope)
+                objtype = qualified_type(scope)
             end
 
-            title = title.collect { |t| Puppet::Parser::Resource::Reference.new(
-                :type => resource_type, :title => t
-            ) }
-            return title.pop if title.length == 1
-            return title
+            return Puppet::Parser::Resource::Reference.new(
+                :type => objtype, :title => title
+            )
         end
 
         # Look up a fully qualified class name.
diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/vardef.rb
index a3094ac..ee79159 100644
--- a/lib/puppet/parser/ast/vardef.rb
+++ b/lib/puppet/parser/ast/vardef.rb
@@ -3,7 +3,7 @@ require 'puppet/parser/ast/branch'
 class Puppet::Parser::AST
     # Define a variable.  Stores the value in the current scope.
     class VarDef < AST::Branch
-        attr_accessor :name, :value, :append
+        attr_accessor :name, :value
 
         @settor = true
 
@@ -14,7 +14,7 @@ class Puppet::Parser::AST
             value = @value.safeevaluate(scope)
 
             parsewrap do
-                scope.setvar(name,value, @file, @line, @append)
+                scope.setvar(name,value, @file, @line)
             end
         end
 
diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb
index 0f90725..2699dc6 100644
--- a/lib/puppet/parser/collector.rb
+++ b/lib/puppet/parser/collector.rb
@@ -6,12 +6,6 @@ class Puppet::Parser::Collector
     # Call the collection method, mark all of the returned objects as non-virtual,
     # and then delete this object from the list of collections to evaluate.
     def evaluate
-        # Shortcut if we're not using storeconfigs and they're trying to collect
-        # exported resources.
-        if form == :exported and Puppet[:storeconfigs] != true
-            Puppet.warning "Not collecting exported resources without storeconfigs"
-            return false
-        end
         if self.resources
             if objects = collect_resources and ! objects.empty?
                 return objects
@@ -72,8 +66,7 @@ class Puppet::Parser::Collector
     def collect_exported
         # First get everything from the export table.  Just reuse our
         # collect_virtual method but tell it to use 'exported? for the test.
-        resources = collect_virtual(true).reject { |r| ! r.virtual? }.each { |r| r.exported = false }
-        #resources = collect_virtual(true).reject { |r| ! r.virtual? }
+        resources = collect_virtual(true).reject { |r| ! r.virtual? }
 
         count = resources.length
 
diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb
index d67b3d2..8fba411 100644
--- a/lib/puppet/parser/compiler.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -332,7 +332,7 @@ class Puppet::Parser::Compiler
 
         unless remaining.empty?
             fail Puppet::ParseError,
-                "Could not find resource(s) %s for overriding" % remaining.collect { |o|
+                "Could not find object(s) %s" % remaining.collect { |o|
                     o.ref
                 }.join(", ")
         end
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
index 5fb0439..e0b60e1 100644
--- a/lib/puppet/parser/functions.rb
+++ b/lib/puppet/parser/functions.rb
@@ -6,8 +6,6 @@ module Functions
     # A module for managing parser functions.  Each specified function
     # becomes an instance method on the Scope class.
 
-    @functions = {}
-
     class << self
         include Puppet::Util
     end
@@ -25,6 +23,7 @@ module Functions
 
     # Create a new function type.
     def self.newfunction(name, options = {}, &block)
+        @functions ||= {}
         name = symbolize(name)
 
         if @functions.include? name
@@ -106,15 +105,202 @@ module Functions
             return false
         end
     end
-  
-    # Runs a newfunction to create a function for each of the log levels
 
-    Puppet::Util::Log.levels.each do |level|
+    # Include the specified classes
+    newfunction(:include, :doc => "Evaluate one or more classes.") do |vals|
+        vals = [vals] unless vals.is_a?(Array)
+
+        # The 'false' disables lazy evaluation.
+        klasses = compiler.evaluate_classes(vals, self, false)
+
+        missing = vals.find_all do |klass|
+            ! klasses.include?(klass)
+        end
+
+        unless missing.empty?
+            # Throw an error if we didn't evaluate all of the classes.
+            str = "Could not find class"
+            if missing.length > 1
+                str += "es"
+            end
+
+            str += " " + missing.join(", ")
+
+            if n = namespaces and ! n.empty? and n != [""]
+                str += " in namespaces %s" % @namespaces.join(", ")
+            end
+            self.fail Puppet::ParseError, str
+        end
+    end
+
+    # Tag the current scope with each passed name
+    newfunction(:tag, :doc => "Add the specified tags to the containing class
+    or definition.  All contained objects will then acquire that tag, also.
+    ") do |vals|
+        self.resource.tag(*vals)
+    end
+
+    # Test whether a given tag is set.  This functions as a big OR -- if any of the
+    # specified tags are unset, we return false.
+    newfunction(:tagged, :type => :rvalue, :doc => "A boolean function that
+    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 = compiler.catalog.tags
+        resourcetags = resource.tags
+
+        retval = true
+        vals.each do |val|
+            unless configtags.include?(val) or resourcetags.include?(val)
+                retval = false
+                break
+            end
+        end
+
+        return retval
+    end
+
+    # Test whether a given class or definition is defined
+    newfunction(:defined, :type => :rvalue, :doc => "Determine whether a given
+    type is defined, either as a native type or a defined type, or whether a class is defined.
+    This is useful for checking whether a class is defined and only including it if it is.
+    This function can also test whether a resource has been defined, using resource references
+    (e.g., ``if defined(File['/tmp/myfile'] { ... }``).  This function is unfortunately
+    dependent on the parse order of the configuration when testing whether a resource is defined.") do |vals|
+        result = false
+        vals.each do |val|
+            case val
+            when String:
+                # For some reason, it doesn't want me to return from here.
+                if Puppet::Type.type(val) or finddefine(val) or findclass(val)
+                    result = true
+                    break
+                end
+            when Puppet::Parser::Resource::Reference:
+                if findresource(val.to_s)
+                    result = true
+                    break
+                end
+            else
+                raise ArgumentError, "Invalid argument of type %s to 'defined'" % val.class
+            end
+        end
+        result
+    end
+
+    newfunction(:fail, :doc => "Fail with a parse error.") do |vals|
+        vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array
+        raise Puppet::ParseError, vals.to_s
+    end
+
+    # Runs a newfunction to create a function for each of the log levels
+    Puppet::Util::Log.levels.each do |level|      
         newfunction(level, :doc => "Log a message on the server at level
-        #{level.to_s}.") do |vals|
-            send(level, vals.join(" "))
+        #{level.to_s}.") do |vals| 
+            send(level, vals.join(" ")) 
+        end 
+    end
+
+    newfunction(:template, :type => :rvalue, :doc => "Evaluate a template and
+    return its value.  See `the templating docs </trac/puppet/wiki/PuppetTemplating>`_
+    for more information.  Note that if multiple templates are specified, their
+    output is all concatenated and returned as the output of the function.
+    ") do |vals|
+        require 'erb'
+
+        vals.collect do |file|
+            # Use a wrapper, so the template can't get access to the full
+            # Scope object.
+            debug "Retrieving template %s" % file
+            wrapper = Puppet::Parser::TemplateWrapper.new(self, file)
+
+            begin
+                wrapper.result()
+            rescue => detail
+                raise Puppet::ParseError,
+                    "Failed to parse template %s: %s" %
+                        [file, detail]
+            end
+        end.join("")
+    end
+
+    # This is just syntactic sugar for a collection, although it will generally
+    # be a good bit faster.
+    newfunction(:realize, :doc => "Make a virtual object real.  This is useful
+        when you want to know the name of the virtual object and don't want to
+        bother with a full collection.  It is slightly faster than a collection,
+        and, of course, is a bit shorter.  You must pass the object using a
+        reference; e.g.: ``realize User[luke]``." ) do |vals|
+        coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil, :virtual)
+        vals = [vals] unless vals.is_a?(Array)
+        coll.resources = vals
+
+        compiler.add_collection(coll)
+    end
+
+    newfunction(:search, :doc => "Add another namespace for this class to search.
+        This allows you to create classes with sets of definitions and add
+        those classes to another class's search path.") do |vals|
+        vals.each do |val|
+            add_namespace(val)
         end
     end
 
+    newfunction(:file, :type => :rvalue,
+        :doc => "Return the contents of a file.  Multiple files
+        can be passed, and the first file that exists will be read in.") do |vals|
+            ret = nil
+            vals.each do |file|
+                unless file =~ /^#{File::SEPARATOR}/
+                    raise Puppet::ParseError, "Files must be fully qualified"
+                end
+                if FileTest.exists?(file)
+                    ret = File.read(file)
+                    break
+                end
+            end
+            if ret
+                ret
+            else
+                raise Puppet::ParseError, "Could not find any files from %s" %
+                    vals.join(", ")
+            end
+    end
+
+    newfunction(:generate, :type => :rvalue,
+        :doc => "Calls an external command and returns the results of the
+        command.  Any arguments are passed to the external command as
+        arguments.  If the generator does not exit with return code of 0,
+        the generator is considered to have failed and a parse error is
+        thrown.  Generators can only have file separators, alphanumerics, dashes,
+        and periods in them.  This function will attempt to protect you from
+        malicious generator calls (e.g., those with '..' in them), but it can
+        never be entirely safe.  No subshell is used to execute
+        generators, so all shell metacharacters are passed directly to
+        the generator.") do |args|
+
+            unless args[0] =~ /^#{File::SEPARATOR}/
+                raise Puppet::ParseError, "Generators must be fully qualified"
+            end
+
+            unless args[0] =~ /^[-#{File::SEPARATOR}\w.]+$/
+                raise Puppet::ParseError,
+                    "Generators can only contain alphanumerics, file separators, and dashes"
+            end
+
+            if args[0] =~ /\.\./
+                raise Puppet::ParseError,
+                    "Can not use generators with '..' in them."
+            end
+
+            begin
+                output = Puppet::Util.execute(args)
+            rescue Puppet::ExecutionFailure => detail
+                raise Puppet::ParseError, "Failed to execute generator %s: %s" %
+                    [args[0], detail]
+            end
+            output
+    end
 end
 end
+
diff --git a/lib/puppet/parser/functions/defined.rb b/lib/puppet/parser/functions/defined.rb
deleted file mode 100644
index 4e369ae..0000000
--- a/lib/puppet/parser/functions/defined.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# Test whether a given class or definition is defined
-Puppet::Parser::Functions::newfunction(:defined, :type => :rvalue, :doc => "Determine whether a given
-    type is defined, either as a native type or a defined type, or whether a class is defined.
-    This is useful for checking whether a class is defined and only including it if it is.
-    This function can also test whether a resource has been defined, using resource references
-    (e.g., ``if defined(File['/tmp/myfile']) { ... }``).  This function is unfortunately
-    dependent on the parse order of the configuration when testing whether a resource is defined.") do |vals|
-        result = false
-        vals.each do |val|
-            case val
-            when String:
-                # For some reason, it doesn't want me to return from here.
-                if Puppet::Type.type(val) or finddefine(val) or findclass(val)
-                    result = true
-                    break
-                end
-            when Puppet::Parser::Resource::Reference:
-                if findresource(val.to_s)
-                    result = true
-                    break
-                end
-            else
-                raise ArgumentError, "Invalid argument of type %s to 'defined'" % val.class
-            end
-        end
-        result
-end
diff --git a/lib/puppet/parser/functions/fail.rb b/lib/puppet/parser/functions/fail.rb
deleted file mode 100644
index 35b20ee..0000000
--- a/lib/puppet/parser/functions/fail.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Puppet::Parser::Functions::newfunction(:fail, :doc => "Fail with a parse error.") do |vals|
-        vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array
-        raise Puppet::ParseError, vals.to_s
-end
diff --git a/lib/puppet/parser/functions/file.rb b/lib/puppet/parser/functions/file.rb
deleted file mode 100644
index 47b3f96..0000000
--- a/lib/puppet/parser/functions/file.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# Returns the contents of a file
-Puppet::Parser::Functions::newfunction(:file, :type => :rvalue,
-        :doc => "Return the contents of a file.  Multiple files
-        can be passed, and the first file that exists will be read in.") do |vals|
-            ret = nil
-            vals.each do |file|
-                unless file =~ /^#{File::SEPARATOR}/
-                    raise Puppet::ParseError, "Files must be fully qualified"
-                end
-                if FileTest.exists?(file)
-                    ret = File.read(file)
-                    break
-                end
-            end
-            if ret
-                ret
-            else
-                raise Puppet::ParseError, "Could not find any files from %s" %
-                    vals.join(", ")
-            end
-end
diff --git a/lib/puppet/parser/functions/fqdn_rand.rb b/lib/puppet/parser/functions/fqdn_rand.rb
deleted file mode 100644
index 2ae46de..0000000
--- a/lib/puppet/parser/functions/fqdn_rand.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-Puppet::Parser::Functions::newfunction(:fqdn_rand, :type => :rvalue, :doc => 
-    "Generates random numbers based on the node's fqdn. The first argument 
-    sets the range.  The second argument specifies a number to add to the 
-    seed and is optional.") do |args|
-        require 'md5'
-        max = args[0]
-        if args[1] then
-             seed = args[1]
-        else
-             seed = 1
-        end
-        fqdn_seed = MD5.new(lookupvar('fqdn')).to_s.hex
-        srand(seed+fqdn_seed)
-        rand(max).to_s
-end
diff --git a/lib/puppet/parser/functions/generate.rb b/lib/puppet/parser/functions/generate.rb
deleted file mode 100644
index 1be9016..0000000
--- a/lib/puppet/parser/functions/generate.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# Runs an external command and returns the results
-Puppet::Parser::Functions::newfunction(:generate, :type => :rvalue,
-        :doc => "Calls an external command and returns the results of the
-        command.  Any arguments are passed to the external command as
-        arguments.  If the generator does not exit with return code of 0,
-        the generator is considered to have failed and a parse error is
-        thrown.  Generators can only have file separators, alphanumerics, dashes,
-        and periods in them.  This function will attempt to protect you from
-        malicious generator calls (e.g., those with '..' in them), but it can
-        never be entirely safe.  No subshell is used to execute
-        generators, so all shell metacharacters are passed directly to
-        the generator.") do |args|
-
-            unless args[0] =~ /^#{File::SEPARATOR}/
-                raise Puppet::ParseError, "Generators must be fully qualified"
-            end
-
-            unless args[0] =~ /^[-#{File::SEPARATOR}\w.]+$/
-                raise Puppet::ParseError,
-                    "Generators can only contain alphanumerics, file separators, and dashes"
-            end
-
-            if args[0] =~ /\.\./
-                raise Puppet::ParseError,
-                    "Can not use generators with '..' in them."
-            end
-
-            begin
-                output = Puppet::Util.execute(args)
-            rescue Puppet::ExecutionFailure => detail
-                raise Puppet::ParseError, "Failed to execute generator %s: %s" %
-                    [args[0], detail]
-            end
-            output
-end
diff --git a/lib/puppet/parser/functions/include.rb b/lib/puppet/parser/functions/include.rb
deleted file mode 100644
index 213a041..0000000
--- a/lib/puppet/parser/functions/include.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# Include the specified classes
-Puppet::Parser::Functions::newfunction(:include, :doc => "Evaluate one or more classes.") do |vals|
-        vals = [vals] unless vals.is_a?(Array)
-
-        # The 'false' disables lazy evaluation.
-        klasses = compiler.evaluate_classes(vals, self, false)
-
-        missing = vals.find_all do |klass|
-            ! klasses.include?(klass)
-        end
-
-        unless missing.empty?
-            # Throw an error if we didn't evaluate all of the classes.
-            str = "Could not find class"
-            if missing.length > 1
-                str += "es"
-            end
-
-            str += " " + missing.join(", ")
-
-            if n = namespaces and ! n.empty? and n != [""]
-                str += " in namespaces %s" % @namespaces.join(", ")
-            end
-            self.fail Puppet::ParseError, str
-        end
-end
diff --git a/lib/puppet/parser/functions/realize.rb b/lib/puppet/parser/functions/realize.rb
deleted file mode 100644
index 1bdde23..0000000
--- a/lib/puppet/parser/functions/realize.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# This is just syntactic sugar for a collection, although it will generally
-# be a good bit faster.
-
-Puppet::Parser::Functions::newfunction(:realize, :doc => "Make a virtual object real.  This is useful
-        when you want to know the name of the virtual object and don't want to
-        bother with a full collection.  It is slightly faster than a collection,
-        and, of course, is a bit shorter.  You must pass the object using a
-        reference; e.g.: ``realize User[luke]``." ) do |vals|
-        coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil, :virtual)
-        vals = [vals] unless vals.is_a?(Array)
-        coll.resources = vals
-
-        compiler.add_collection(coll)
-end
diff --git a/lib/puppet/parser/functions/search.rb b/lib/puppet/parser/functions/search.rb
deleted file mode 100644
index 87dd02d..0000000
--- a/lib/puppet/parser/functions/search.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-Puppet::Parser::Functions::newfunction(:search, :doc => "Add another namespace for this class to search.
-        This allows you to create classes with sets of definitions and add
-        those classes to another class's search path.") do |vals|
-        vals.each do |val|
-            add_namespace(val)
-        end
-end
diff --git a/lib/puppet/parser/functions/sha1.rb b/lib/puppet/parser/functions/sha1.rb
deleted file mode 100644
index 09386a6..0000000
--- a/lib/puppet/parser/functions/sha1.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Puppet::Parser::Functions::newfunction(:sha1, :type => :rvalue,
-        :doc => "Returns a SHA1 hash value from a provided string.") do |args|
-            require 'sha1'
-
-            Digest::SHA1.hexdigest(args[0])
-end
diff --git a/lib/puppet/parser/functions/tag.rb b/lib/puppet/parser/functions/tag.rb
deleted file mode 100644
index 3e487fe..0000000
--- a/lib/puppet/parser/functions/tag.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# Tag the current scope with each passed name
-Puppet::Parser::Functions::newfunction(:tag, :doc => "Add the specified tags to the containing class
-    or definition.  All contained objects will then acquire that tag, also.
-    ") do |vals|
-        self.resource.tag(*vals)
-end
diff --git a/lib/puppet/parser/functions/tagged.rb b/lib/puppet/parser/functions/tagged.rb
deleted file mode 100644
index fccb132..0000000
--- a/lib/puppet/parser/functions/tagged.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# Test whether a given tag is set.  This functions as a big OR -- if any of the specified tags are unset, we return false.
-Puppet::Parser::Functions::newfunction(:tagged, :type => :rvalue, :doc => "A boolean function that
-    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 = compiler.catalog.tags
-        resourcetags = resource.tags
-
-        retval = true
-        vals.each do |val|
-            unless configtags.include?(val) or resourcetags.include?(val)
-                retval = false
-                break
-            end
-        end
-
-        return retval
-end
diff --git a/lib/puppet/parser/functions/template.rb b/lib/puppet/parser/functions/template.rb
deleted file mode 100644
index e62c3b3..0000000
--- a/lib/puppet/parser/functions/template.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-Puppet::Parser::Functions::newfunction(:template, :type => :rvalue, :doc => 
-    "Evaluate a template and return its value.  See `the templating docs 
-    </trac/puppet/wiki/PuppetTemplating>`_ for more information.  Note that 
-    if multiple templates are specified, their output is all concatenated 
-    and returned as the output of the function.") do |vals|
-        require 'erb'
-
-        vals.collect do |file|
-            # Use a wrapper, so the template can't get access to the full
-            # Scope object.
-            debug "Retrieving template %s" % file
-            wrapper = Puppet::Parser::TemplateWrapper.new(self, file)
-
-            begin
-                wrapper.result()
-            rescue => detail
-                raise Puppet::ParseError,
-                    "Failed to parse template %s: %s" %
-                        [file, detail]
-            end
-        end.join("")
-end
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
new file mode 100644
index 0000000..484efe8
--- /dev/null
+++ b/lib/puppet/parser/grammar.ra
@@ -0,0 +1,648 @@
+# vim: syntax=ruby
+
+# the parser
+
+class Puppet::Parser::Parser
+
+token LBRACK DQTEXT SQTEXT RBRACK LBRACE RBRACE SYMBOL FARROW COMMA TRUE
+token FALSE EQUALS LESSEQUAL NOTEQUAL DOT COLON LLCOLLECT RRCOLLECT
+token QMARK LPAREN RPAREN ISEQUAL GREATEREQUAL GREATERTHAN LESSTHAN
+token IF ELSE IMPORT DEFINE ELSIF VARIABLE CLASS INHERITS NODE BOOLEAN
+token NAME SEMIC CASE DEFAULT AT LCOLLECT RCOLLECT CLASSNAME CLASSREF
+token NOT OR AND UNDEF PARROW
+
+rule
+program:    statements {
+    if val[0]
+        # Make sure we always return an array.
+        if val[0].is_a?(AST::ASTArray)
+            if val[0].children.empty?
+                result = nil
+            else
+                result = val[0]
+            end
+        else
+            result = aryfy(val[0])
+        end
+    else
+        result = nil
+    end
+}
+            | nil
+
+statements:   statement
+            | statements statement {
+    if val[0] and val[1]
+        if val[0].instance_of?(AST::ASTArray)
+            val[0].push(val[1])
+            result = val[0]
+        else
+            result = ast AST::ASTArray, :children => [val[0],val[1]]
+        end
+    elsif obj = (val[0] || val[1])
+        result = obj
+    else result = nil
+    end
+}
+
+# The main list of valid statements
+statement:    resource
+            | virtualresource
+            | collection
+            | assignment
+            | casestatement
+            | ifstatement
+            | import
+            | fstatement
+            | definition
+            | hostclass
+            | nodedef
+            | resourceoverride
+
+fstatement:   NAME LPAREN funcvalues RPAREN {
+    args = aryfy(val[2])
+    result = ast AST::Function,
+        :name => val[0],
+        :arguments => args,
+        :ftype => :statement
+}
+            | NAME LPAREN RPAREN {
+    result = ast AST::Function,
+        :name => val[0],
+        :arguments => AST::ASTArray.new({}),
+        :ftype => :statement
+}
+            | NAME funcvalues {
+    args = aryfy(val[1])
+    result = ast AST::Function,
+        :name => val[0],
+        :arguments => args,
+        :ftype => :statement
+}
+
+funcvalues:       namestrings
+                | resourcerefs
+
+namestrings:      namestring
+                | namestrings COMMA namestring {
+    result = aryfy(val[0], val[2])
+    result.line = @lexer.line
+    result.file = @lexer.file
+}
+
+# This is *almost* an rvalue, but I couldn't get a full
+# rvalue to work without scads of shift/reduce conflicts.
+namestring:       name
+                | variable
+                | type
+                | boolean
+                | funcrvalue
+                | selector
+                | quotedtext
+                | CLASSNAME {
+                    result = ast AST::Name, :value => val[0]
+                }
+
+resourcerefs:     resourceref
+                | resourcerefs COMMA resourceref {
+    unless val[0].is_a?(AST::ASTArray)
+        val[0] = aryfy(val[0])
+    end
+
+    val[0].push(val[2])
+
+    result = val[0]
+}
+
+resource:       classname LBRACE resourceinstances endsemi RBRACE {
+    array = val[2]
+    if array.instance_of?(AST::ResourceInstance)
+        array = [array]
+    end
+    result = ast AST::ASTArray
+
+    # this iterates across each specified resourceinstance
+    array.each { |instance|
+        unless instance.instance_of?(AST::ResourceInstance)
+            raise Puppet::Dev, "Got something that isn't an instance"
+        end
+        # now, i need to somehow differentiate between those things with
+        # arrays in their names, and normal things
+        result.push ast(AST::Resource,
+            :type => val[0],
+            :title => instance[0],
+            :params => instance[1])
+    }
+}           | classname LBRACE params endcomma RBRACE {
+    # This is a deprecated syntax.
+    error "All resource specifications require names"
+}           | classref LBRACE params endcomma RBRACE {
+    # a defaults setting for a type
+    result = ast(AST::ResourceDefaults, :type => val[0], :params => val[2])
+}
+
+# Override a value set elsewhere in the configuration.
+resourceoverride:     resourceref LBRACE anyparams endcomma RBRACE {
+    result = ast AST::ResourceOverride, :object => val[0], :params => val[2]
+}
+
+# Exported and virtual resources; these don't get sent to the client
+# unless they get collected elsewhere in the db.
+virtualresource:  at resource {
+    type = val[0]
+
+    if (type == :exported and ! Puppet[:storeconfigs]) and ! Puppet[:parseonly]
+        error "You cannot collect without storeconfigs being set"
+    end
+
+    if val[1].is_a? AST::ResourceDefaults
+        error "Defaults are not virtualizable"
+    end
+
+    method = type.to_s + "="
+
+    # Just mark our resources as exported and pass them through.
+    if val[1].instance_of?(AST::ASTArray)
+        val[1].each do |obj|
+            obj.send(method, true)
+        end
+    else
+        val[1].send(method, true)
+    end
+
+    result = val[1]
+}
+
+at:   AT { result = :virtual }
+    | AT AT { result = :exported }
+
+# A collection statement.  Currently supports no arguments at all, but eventually
+# will, I assume.
+collection:     classref collectrhand {
+    if val[0] =~ /^[a-z]/
+        Puppet.warning addcontext("Collection names must now be capitalized")
+    end
+    type = val[0].downcase
+    args = {:type => type}
+
+    if val[1].is_a?(AST::CollExpr)
+        args[:query] = val[1]
+        args[:query].type = type
+        args[:form] = args[:query].form
+    else
+        args[:form] = val[1]
+    end
+    if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
+        error "You cannot collect exported resources without storeconfigs being set"
+    end
+    result = ast AST::Collection, args
+}
+
+
+collectrhand:     LCOLLECT collstatements RCOLLECT {
+    if val[1]
+        result = val[1]
+        result.form = :virtual
+    else
+        result = :virtual
+    end
+}
+                | LLCOLLECT collstatements RRCOLLECT {
+    if val[1]
+        result = val[1]
+        result.form = :exported
+    else
+        result = :exported
+    end
+}
+
+# A mini-language for handling collection comparisons.  This is organized
+# to avoid the need for precedence indications.
+collstatements:           nil
+                        | collstatement
+                        | collstatements colljoin collstatement {
+    result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
+}
+
+collstatement:            collexpr
+                        | LPAREN collstatements RPAREN {
+    result = val[1]
+    result.parens = true
+}
+
+colljoin:                 AND | OR
+
+collexpr:                 colllval ISEQUAL simplervalue {
+    result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
+    #result = ast AST::CollExpr
+    #result.push *val
+}
+                        | colllval NOTEQUAL simplervalue {
+    result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
+    #result = ast AST::CollExpr
+    #result.push *val
+}
+
+colllval:                 variable
+                        | name
+
+resourceinst:   resourcename COLON params endcomma {
+    result = ast AST::ResourceInstance, :children => [val[0],val[2]]
+}
+
+resourceinstances:   resourceinst
+                 | resourceinstances SEMIC resourceinst {
+    if val[0].instance_of?(AST::ResourceInstance)
+        result = ast AST::ASTArray, :children => [val[0],val[2]]
+    else
+        val[0].push val[2]
+        result = val[0]
+    end
+}
+
+endsemi:      # nothing
+            | SEMIC
+
+undef:         UNDEF {
+    result = ast AST::Undef, :value => :undef
+}
+
+name:         NAME {
+    result = ast AST::Name, :value => val[0]
+}
+
+type:         CLASSREF {
+    result = ast AST::Type, :value => val[0]
+}
+
+resourcename:   quotedtext
+            | name
+            | type
+            | selector
+            | variable
+            | array
+
+assignment:     VARIABLE EQUALS rvalue {
+    if val[0] =~ /::/
+        raise Puppet::ParseError, "Cannot assign to variables in other namespaces"
+    end
+    # this is distinct from referencing a variable
+    variable = ast AST::Name, :value => val[0]
+    result = ast AST::VarDef, :name => variable, :value => val[2]
+}
+
+params:   # nothing
+{
+    result = ast AST::ASTArray
+}
+        | param { result = val[0] }
+        | params COMMA param {
+    if val[0].instance_of?(AST::ASTArray)
+        val[0].push(val[2])
+        result = val[0]
+    else
+        result = ast AST::ASTArray, :children => [val[0],val[2]]
+    end
+}
+
+param:        NAME FARROW rvalue {
+    result = ast AST::ResourceParam, :param => val[0], :value => val[2]
+}
+
+addparam:     NAME PARROW rvalue {
+    result = ast AST::ResourceParam, :param => val[0], :value => val[2],
+                                     :add => true
+}
+
+anyparam:     param
+            | addparam
+
+anyparams:   # nothing
+{
+    result = ast AST::ASTArray
+}
+        | anyparam { result = val[0] }
+        | anyparams COMMA anyparam {
+    if val[0].instance_of?(AST::ASTArray)
+        val[0].push(val[2])
+        result = val[0]
+    else
+        result = ast AST::ASTArray, :children => [val[0],val[2]]
+    end
+}
+
+rvalues:      rvalue
+            | rvalues comma rvalue {
+    if val[0].instance_of?(AST::ASTArray)
+        result = val[0].push(val[2])
+    else
+        result = ast AST::ASTArray, :children => [val[0],val[2]]
+    end
+}
+
+simplervalue:       quotedtext
+            | name
+            | type
+            | boolean
+            | selector
+            | variable
+
+rvalue:       quotedtext
+            | name
+            | type
+            | boolean
+            | selector
+            | variable
+            | array
+            | resourceref
+            | funcrvalue
+            | undef
+
+# We currently require arguments in these functions.
+funcrvalue:   NAME LPAREN funcvalues RPAREN {
+    args = aryfy(val[2])
+    result = ast AST::Function,
+        :name => val[0],
+        :arguments => args,
+        :ftype => :rvalue
+}           | NAME LPAREN RPAREN {
+    result = ast AST::Function,
+        :name => val[0],
+        :arguments => AST::ASTArray.new({}),
+        :ftype => :rvalue
+}
+
+quotedtext: DQTEXT {
+    result = ast AST::String, :value => val[0]
+}           | SQTEXT {
+    result = ast AST::FlatString, :value => val[0]
+}
+
+boolean:    BOOLEAN {
+    result = ast AST::Boolean, :value => val[0]
+}
+
+resourceref: NAME LBRACK rvalue RBRACK {
+    Puppet.warning addcontext("Deprecation notice:  Resource references should now be capitalized")
+    result = ast AST::ResourceReference, :type => val[0], :title => val[2]
+}               | classref LBRACK rvalue RBRACK {
+    result = ast AST::ResourceReference, :type => val[0], :title => val[2]
+}
+
+ifstatement:      IF iftest LBRACE statements RBRACE else {
+    args = {
+        :test => val[1],
+        :statements => val[3]
+    }
+
+    if val[5]
+        args[:else] = val[5]
+    end
+
+    result = ast AST::IfStatement, args
+}
+
+else:             # nothing
+                | ELSE LBRACE statements RBRACE {
+    result = ast AST::Else, :statements => val[2]
+}
+
+# Currently we only support a single value, but eventually one assumes
+# we'll support operators and such.
+iftest:         rvalue
+
+casestatement:  CASE rvalue LBRACE caseopts RBRACE {
+    options = val[3]
+    unless options.instance_of?(AST::ASTArray)
+        options = ast AST::ASTArray, :children => [val[3]]
+    end
+    result = ast AST::CaseStatement, :test => val[1], :options => options
+}
+
+caseopts:     caseopt
+            | caseopts caseopt {
+    if val[0].instance_of?(AST::ASTArray)
+        val[0].push val[1]
+        result = val[0]
+    else
+        result = ast AST::ASTArray, :children => [val[0], val[1]]
+    end
+}
+
+caseopt:        casevalues COLON LBRACE statements RBRACE {
+    result = ast AST::CaseOpt, :value => val[0], :statements => val[3]
+}               | casevalues COLON LBRACE RBRACE {
+    result = ast(AST::CaseOpt,
+        :value => val[0],
+        :statements => ast(AST::ASTArray)
+    )
+}
+
+casevalues:       selectlhand
+                | casevalues COMMA selectlhand {
+    if val[0].instance_of?(AST::ASTArray)
+        val[0].push(val[2])
+        result = val[0]
+    else
+        result = ast AST::ASTArray, :children => [val[0],val[2]]
+    end
+}
+
+selector:     selectlhand QMARK svalues {
+    result = ast AST::Selector, :param => val[0], :values => val[2]
+}
+
+svalues:      selectval
+            | LBRACE sintvalues endcomma RBRACE { result = val[1] }
+
+sintvalues:   selectval
+            | sintvalues comma selectval {
+    if val[0].instance_of?(AST::ASTArray)
+        val[0].push(val[2])
+        result = val[0]
+    else
+        result = ast AST::ASTArray, :children => [val[0],val[2]]
+    end
+}
+
+selectval:        selectlhand FARROW rvalue {
+    result = ast AST::ResourceParam, :param => val[0], :value => val[2]
+}
+
+selectlhand:  name
+            | type
+            | quotedtext
+            | variable
+            | funcrvalue
+            | boolean
+            | undef
+            | DEFAULT {
+    result = ast AST::Default, :value => val[0]
+}
+
+# These are only used for importing, and we don't interpolate there.
+qtexts:       quotedtext { result = [val[0].value] }
+            | qtexts COMMA quotedtext {
+    results = val[0] << val[2].value
+}
+
+import: IMPORT qtexts {
+    val[1].each do |file|
+        import(file)
+    end
+
+    result = AST::ASTArray.new(:children => [])
+}
+
+# Disable definition inheritance for now. 8/27/06, luke
+#definition: DEFINE NAME argumentlist parent LBRACE statements RBRACE {
+definition: DEFINE classname argumentlist LBRACE statements RBRACE {
+    newdefine classname(val[1]), :arguments => val[2], :code => val[4]
+    @lexer.indefine = false
+    result = nil
+
+#}           | DEFINE NAME argumentlist parent LBRACE RBRACE {
+}           | DEFINE classname argumentlist LBRACE RBRACE {
+    newdefine classname(val[1]), :arguments => val[2]
+    @lexer.indefine = false
+    result = nil
+}
+
+#hostclass: CLASS NAME argumentlist parent LBRACE statements RBRACE {
+hostclass: CLASS classname classparent LBRACE statements RBRACE {
+    # Our class gets defined in the parent namespace, not our own.
+    @lexer.namepop
+    newclass classname(val[1]), :code => val[4], :parent => val[2]
+    result = nil
+}           | CLASS classname classparent LBRACE RBRACE {
+    # Our class gets defined in the parent namespace, not our own.
+    @lexer.namepop
+    newclass classname(val[1]), :parent => val[2]
+    result = nil
+}
+
+nodedef: NODE hostnames nodeparent LBRACE statements RBRACE {
+    newnode val[1], :parent => val[2], :code => val[4]
+    result = nil
+}       |  NODE hostnames nodeparent LBRACE RBRACE {
+    newnode val[1], :parent => val[2]
+    result = nil
+}
+
+classref:       CLASSREF
+
+classname:       NAME
+            | CLASSNAME
+
+# Multiple hostnames, as used for node names.  These are all literal
+# strings, not AST objects.
+hostnames:    hostname 
+  | hostnames COMMA hostname {
+    result = val[0]
+    result = [result] unless result.is_a?(Array)
+    result << val[2]
+}
+
+hostname: NAME
+        | SQTEXT
+        | DQTEXT
+        | DEFAULT
+
+nil:    {
+    result = nil
+}
+
+nothing:    {
+    result = ast AST::ASTArray, :children => []
+}
+
+argumentlist: nil
+            | LPAREN nothing RPAREN {
+    result = nil
+}
+            | LPAREN arguments RPAREN {
+    result = val[1]
+    result = [result] unless result[0].is_a?(Array)
+}
+
+arguments:    argument
+            | arguments COMMA argument {
+    result = val[0]
+    result = [result] unless result[0].is_a?(Array)
+    result << val[2]
+}
+
+argument:     NAME EQUALS rvalue {
+    Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
+    result = [val[0], val[2]]
+}
+            | NAME {
+    Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
+    result = [val[0]]
+}           | VARIABLE EQUALS rvalue {
+    result = [val[0], val[2]]
+}           | VARIABLE {
+    result = [val[0]]
+}
+
+nodeparent:       nil
+            | INHERITS hostname {
+    result = val[1]
+}
+
+classparent:       nil
+            | INHERITS classnameordefault {
+    result = val[1]
+}
+
+classnameordefault: classname | DEFAULT
+
+variable:     VARIABLE {
+    result = ast AST::Variable, :value => val[0]
+}
+
+array:        LBRACK rvalues RBRACK {
+    if val[1].instance_of?(AST::ASTArray)
+        result = val[1]
+    else
+        result = ast AST::ASTArray, :children => [val[1]]
+    end
+}           | LBRACK RBRACK {
+    result = ast AST::ASTArray
+}
+
+comma:        FARROW
+            | COMMA
+
+endcomma:     # nothing
+            | COMMA { result = nil }
+
+end
+---- header ----
+require 'puppet'
+require 'puppet/util/loadedfile'
+require 'puppet/parser/lexer'
+require 'puppet/parser/ast'
+#require 'puppet/parser/interpreter'
+
+module Puppet
+    class ParseError < Puppet::Error; end
+    class ImportError < Racc::ParseError; end
+    class AlreadyImportedError < ImportError; end
+end
+
+Puppet[:typecheck] = true
+Puppet[:paramcheck] = true
+
+---- inner ----
+
+# It got too annoying having code in a file that needs to be compiled.
+require 'puppet/parser/parser_support'
+
+# Make emacs happy
+# Local Variables:
+# mode: ruby
+# End:
+
+# $Id$
+
diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb
index 423c34a..f27c1c5 100644
--- a/lib/puppet/parser/interpreter.rb
+++ b/lib/puppet/parser/interpreter.rb
@@ -50,8 +50,23 @@ class Puppet::Parser::Interpreter
     # Return the parser for a specific environment.
     def parser(environment)
         if ! @parsers[environment] or @parsers[environment].reparse?
-            # This will throw an exception if it does not succeed.
-            @parsers[environment] = create_parser(environment)
+            # This will throw an exception if it does not succeed.  We only
+            # want to get rid of the old parser if we successfully create a new
+            # one.
+            begin
+                tmp = create_parser(environment)
+                @parsers[environment].clear if @parsers[environment]
+                @parsers[environment] = tmp
+            rescue => detail
+                # If a parser already exists, than assume that we logged the
+                # exception elsewhere and reuse the parser.  If one doesn't
+                # exist, then reraise.
+                if @parsers[environment]
+                    Puppet.err detail
+                else
+                    raise detail
+                end
+            end
         end
         @parsers[environment]
     end
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index 9226434..51026ea 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -105,7 +105,6 @@ class Puppet::Parser::Lexer
         '(' => :LPAREN,
         ')' => :RPAREN,
         '=' => :EQUALS,
-        '+=' => :APPENDS,
         '==' => :ISEQUAL,
         '>=' => :GREATEREQUAL,
         '>' => :GREATERTHAN,
@@ -126,23 +125,13 @@ class Puppet::Parser::Lexer
         '\\' => :BACKSLASH,
         '=>' => :FARROW,
         '+>' => :PARROW,
-        '+' => :PLUS,
-        '-' => :MINUS,
-        '/' => :DIV,
-        '*' => :TIMES,
-        '<<' => :LSHIFT,
-        '>>' => :RSHIFT,
         %r{([a-z][-\w]*::)+[a-z][-\w]*} => :CLASSNAME,
         %r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF
     )
 
     TOKENS.add_tokens "Whatever" => :DQTEXT, "Nomatter" => :SQTEXT, "alsonomatter" => :BOOLEAN
 
-    TOKENS.add_token :NUMBER, %r{\b(?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?)\b} do |lexer, value|
-        [TOKENS[:NAME], value]
-    end
-
-    TOKENS.add_token :NAME, %r{[a-z0-9][-\w]*} do |lexer, value|
+    TOKENS.add_token :NAME, %r{[a-z][-\w]*} do |lexer, value|
         string_token = self
         # we're looking for keywords here
         if tmp = KEYWORDS.lookup(value)
@@ -155,6 +144,10 @@ class Puppet::Parser::Lexer
         [string_token, value]
     end
 
+    TOKENS.add_token :NUMBER, %r{[0-9]+} do |lexer, value|
+        [TOKENS[:NAME], value]
+    end
+
     TOKENS.add_token :COMMENT, %r{#.*}, :skip => true
 
     TOKENS.add_token :RETURN, "\n", :skip => true, :incr_line => true, :skip_text => true
@@ -438,9 +431,6 @@ class Puppet::Parser::Lexer
             str.gsub!(/\\#{quote}/,quote)
         end
 
-        # Add to our line count for every carriage return in multi-line strings.
-        @line += str.count("\n")
-
         return str
     end
 
diff --git a/lib/puppet/parser/makefile b/lib/puppet/parser/makefile
new file mode 100644
index 0000000..c4911d0
--- /dev/null
+++ b/lib/puppet/parser/makefile
@@ -0,0 +1,8 @@
+#parser.rb: grammar.ry
+#	ryacc --output parser grammar
+
+parser.rb: grammar.ra
+	racc -o$@ grammar.ra
+
+grammar.output: grammar.ra
+	racc -v -o$@ grammar.ra
diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb
index 713f93e..e27a209 100644
--- a/lib/puppet/parser/parser.rb
+++ b/lib/puppet/parser/parser.rb
@@ -29,7 +29,7 @@ module Puppet
 
     class Parser < Racc::Parser
 
-module_eval <<'..end grammar.ra modeval..id5cb4445525', 'grammar.ra', 741
+module_eval <<'..end grammar.ra modeval..idfef5d70c9f', 'grammar.ra', 638
 
 # It got too annoying having code in a file that needs to be compiled.
 require 'puppet/parser/parser_support'
@@ -41,690 +41,517 @@ require 'puppet/parser/parser_support'
 
 # $Id$
 
-..end grammar.ra modeval..id5cb4445525
+..end grammar.ra modeval..idfef5d70c9f
 
 ##### racc 1.4.5 generates ###
 
 racc_reduce_table = [
  0, 0, :racc_error,
- 1, 60, :_reduce_1,
- 1, 60, :_reduce_none,
- 1, 61, :_reduce_none,
- 2, 61, :_reduce_4,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 4, 71, :_reduce_18,
- 5, 71, :_reduce_19,
- 3, 71, :_reduce_20,
- 2, 71, :_reduce_21,
- 1, 77, :_reduce_none,
- 1, 77, :_reduce_none,
- 3, 77, :_reduce_24,
- 3, 77, :_reduce_25,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_33,
- 5, 64, :_reduce_34,
- 5, 64, :_reduce_35,
- 5, 64, :_reduce_36,
- 5, 75, :_reduce_37,
- 2, 65, :_reduce_38,
- 1, 94, :_reduce_39,
- 2, 94, :_reduce_40,
- 2, 66, :_reduce_41,
- 3, 95, :_reduce_42,
- 3, 95, :_reduce_43,
+ 1, 52, :_reduce_1,
+ 1, 52, :_reduce_none,
+ 1, 53, :_reduce_none,
+ 2, 53, :_reduce_4,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 4, 63, :_reduce_17,
+ 3, 63, :_reduce_18,
+ 2, 63, :_reduce_19,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 69, :_reduce_none,
+ 3, 69, :_reduce_23,
+ 1, 71, :_reduce_none,
+ 1, 71, :_reduce_none,
+ 1, 71, :_reduce_none,
+ 1, 71, :_reduce_none,
+ 1, 71, :_reduce_none,
+ 1, 71, :_reduce_none,
+ 1, 71, :_reduce_none,
+ 1, 71, :_reduce_31,
+ 1, 70, :_reduce_none,
+ 3, 70, :_reduce_33,
+ 5, 56, :_reduce_34,
+ 5, 56, :_reduce_35,
+ 5, 56, :_reduce_36,
+ 5, 67, :_reduce_37,
+ 2, 57, :_reduce_38,
+ 1, 87, :_reduce_39,
+ 2, 87, :_reduce_40,
+ 2, 58, :_reduce_41,
+ 3, 88, :_reduce_42,
+ 3, 88, :_reduce_43,
+ 1, 89, :_reduce_none,
+ 1, 89, :_reduce_none,
+ 3, 89, :_reduce_46,
+ 1, 90, :_reduce_none,
+ 3, 90, :_reduce_48,
+ 1, 91, :_reduce_none,
+ 1, 91, :_reduce_none,
+ 3, 92, :_reduce_51,
+ 3, 92, :_reduce_52,
+ 1, 93, :_reduce_none,
+ 1, 93, :_reduce_none,
+ 4, 95, :_reduce_55,
+ 1, 81, :_reduce_none,
+ 3, 81, :_reduce_57,
+ 0, 82, :_reduce_none,
+ 1, 82, :_reduce_none,
+ 1, 97, :_reduce_60,
+ 1, 72, :_reduce_61,
+ 1, 74, :_reduce_62,
  1, 96, :_reduce_none,
  1, 96, :_reduce_none,
- 3, 96, :_reduce_46,
- 1, 97, :_reduce_none,
- 3, 97, :_reduce_48,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 3, 99, :_reduce_51,
- 3, 99, :_reduce_52,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_none,
- 4, 102, :_reduce_55,
- 1, 88, :_reduce_none,
- 3, 88, :_reduce_57,
- 0, 89, :_reduce_none,
- 1, 89, :_reduce_none,
- 1, 104, :_reduce_60,
- 1, 80, :_reduce_61,
- 1, 82, :_reduce_62,
- 1, 103, :_reduce_none,
- 1, 103, :_reduce_none,
- 1, 103, :_reduce_none,
- 1, 103, :_reduce_none,
- 1, 103, :_reduce_none,
+ 1, 96, :_reduce_none,
+ 1, 96, :_reduce_none,
+ 1, 96, :_reduce_none,
+ 1, 96, :_reduce_none,
+ 3, 59, :_reduce_69,
+ 0, 83, :_reduce_70,
+ 1, 83, :_reduce_71,
+ 3, 83, :_reduce_72,
+ 3, 100, :_reduce_73,
+ 3, 101, :_reduce_74,
+ 1, 102, :_reduce_none,
+ 1, 102, :_reduce_none,
+ 0, 86, :_reduce_77,
+ 1, 86, :_reduce_78,
+ 3, 86, :_reduce_79,
  1, 103, :_reduce_none,
- 3, 67, :_reduce_69,
- 3, 76, :_reduce_70,
- 0, 90, :_reduce_71,
- 1, 90, :_reduce_72,
- 3, 90, :_reduce_73,
- 3, 107, :_reduce_74,
- 3, 109, :_reduce_75,
+ 3, 103, :_reduce_81,
+ 1, 94, :_reduce_none,
+ 1, 94, :_reduce_none,
+ 1, 94, :_reduce_none,
+ 1, 94, :_reduce_none,
+ 1, 94, :_reduce_none,
+ 1, 94, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 1, 99, :_reduce_none,
+ 4, 76, :_reduce_98,
+ 3, 76, :_reduce_99,
+ 1, 78, :_reduce_100,
+ 1, 78, :_reduce_101,
+ 1, 75, :_reduce_102,
+ 4, 79, :_reduce_103,
+ 4, 79, :_reduce_104,
+ 6, 61, :_reduce_105,
+ 0, 106, :_reduce_none,
+ 4, 106, :_reduce_107,
+ 1, 105, :_reduce_none,
+ 5, 60, :_reduce_109,
+ 1, 107, :_reduce_none,
+ 2, 107, :_reduce_111,
+ 5, 108, :_reduce_112,
+ 4, 108, :_reduce_113,
+ 1, 109, :_reduce_none,
+ 3, 109, :_reduce_115,
+ 3, 77, :_reduce_116,
+ 1, 111, :_reduce_none,
+ 4, 111, :_reduce_118,
+ 1, 113, :_reduce_none,
+ 3, 113, :_reduce_120,
+ 3, 112, :_reduce_121,
  1, 110, :_reduce_none,
  1, 110, :_reduce_none,
- 0, 93, :_reduce_78,
- 1, 93, :_reduce_79,
- 3, 93, :_reduce_80,
- 1, 111, :_reduce_none,
- 3, 111, :_reduce_82,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 101, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 4, 84, :_reduce_99,
- 3, 84, :_reduce_100,
- 1, 86, :_reduce_101,
- 1, 86, :_reduce_102,
- 1, 83, :_reduce_103,
- 4, 79, :_reduce_104,
- 4, 79, :_reduce_105,
- 6, 69, :_reduce_106,
- 5, 69, :_reduce_107,
- 0, 113, :_reduce_none,
- 4, 113, :_reduce_109,
- 3, 113, :_reduce_110,
- 1, 106, :_reduce_none,
- 3, 106, :_reduce_112,
- 3, 106, :_reduce_113,
- 3, 106, :_reduce_114,
- 3, 106, :_reduce_115,
- 3, 106, :_reduce_116,
- 3, 106, :_reduce_117,
- 2, 106, :_reduce_118,
- 3, 106, :_reduce_119,
- 3, 106, :_reduce_120,
- 3, 106, :_reduce_121,
- 3, 106, :_reduce_122,
- 3, 106, :_reduce_123,
- 3, 106, :_reduce_124,
- 2, 106, :_reduce_125,
- 3, 106, :_reduce_126,
- 3, 106, :_reduce_127,
- 3, 106, :_reduce_128,
- 5, 68, :_reduce_129,
- 1, 114, :_reduce_none,
- 2, 114, :_reduce_131,
- 5, 115, :_reduce_132,
- 4, 115, :_reduce_133,
- 1, 116, :_reduce_none,
- 3, 116, :_reduce_135,
- 3, 85, :_reduce_136,
- 1, 118, :_reduce_none,
- 4, 118, :_reduce_138,
- 1, 120, :_reduce_none,
- 3, 120, :_reduce_140,
- 3, 119, :_reduce_141,
- 1, 117, :_reduce_none,
- 1, 117, :_reduce_none,
- 1, 117, :_reduce_none,
- 1, 117, :_reduce_none,
- 1, 117, :_reduce_none,
- 1, 117, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_none,
+ 1, 110, :_reduce_129,
+ 1, 114, :_reduce_130,
+ 3, 114, :_reduce_131,
+ 2, 62, :_reduce_132,
+ 6, 64, :_reduce_133,
+ 5, 64, :_reduce_134,
+ 6, 65, :_reduce_135,
+ 5, 65, :_reduce_136,
+ 6, 66, :_reduce_137,
+ 5, 66, :_reduce_138,
+ 1, 85, :_reduce_none,
+ 1, 80, :_reduce_none,
+ 1, 80, :_reduce_none,
  1, 117, :_reduce_none,
- 1, 117, :_reduce_149,
- 1, 121, :_reduce_150,
- 3, 121, :_reduce_151,
- 2, 70, :_reduce_152,
- 6, 72, :_reduce_153,
- 5, 72, :_reduce_154,
- 6, 73, :_reduce_155,
- 5, 73, :_reduce_156,
- 6, 74, :_reduce_157,
- 5, 74, :_reduce_158,
- 1, 92, :_reduce_none,
- 1, 87, :_reduce_none,
- 1, 87, :_reduce_none,
- 1, 124, :_reduce_none,
- 3, 124, :_reduce_163,
- 1, 126, :_reduce_none,
- 1, 126, :_reduce_none,
- 1, 126, :_reduce_none,
- 1, 126, :_reduce_none,
- 0, 62, :_reduce_168,
- 0, 127, :_reduce_169,
- 1, 122, :_reduce_none,
- 3, 122, :_reduce_171,
- 3, 122, :_reduce_172,
- 1, 128, :_reduce_none,
- 3, 128, :_reduce_174,
- 3, 129, :_reduce_175,
- 1, 129, :_reduce_176,
- 3, 129, :_reduce_177,
- 1, 129, :_reduce_178,
- 1, 125, :_reduce_none,
- 2, 125, :_reduce_180,
+ 3, 117, :_reduce_143,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 1, 119, :_reduce_none,
+ 0, 54, :_reduce_148,
+ 0, 120, :_reduce_149,
+ 1, 115, :_reduce_none,
+ 3, 115, :_reduce_151,
+ 3, 115, :_reduce_152,
+ 1, 121, :_reduce_none,
+ 3, 121, :_reduce_154,
+ 3, 122, :_reduce_155,
+ 1, 122, :_reduce_156,
+ 3, 122, :_reduce_157,
+ 1, 122, :_reduce_158,
+ 1, 118, :_reduce_none,
+ 2, 118, :_reduce_160,
+ 1, 116, :_reduce_none,
+ 2, 116, :_reduce_162,
+ 1, 123, :_reduce_none,
  1, 123, :_reduce_none,
- 2, 123, :_reduce_182,
- 1, 130, :_reduce_none,
- 1, 130, :_reduce_none,
- 1, 81, :_reduce_185,
- 3, 105, :_reduce_186,
- 4, 105, :_reduce_187,
- 2, 105, :_reduce_188,
- 1, 112, :_reduce_none,
- 1, 112, :_reduce_none,
- 0, 91, :_reduce_none,
- 1, 91, :_reduce_192 ]
-
-racc_reduce_n = 193
-
-racc_shift_n = 317
+ 1, 73, :_reduce_165,
+ 3, 98, :_reduce_166,
+ 2, 98, :_reduce_167,
+ 1, 104, :_reduce_none,
+ 1, 104, :_reduce_none,
+ 0, 84, :_reduce_none,
+ 1, 84, :_reduce_171 ]
+
+racc_reduce_n = 172
+
+racc_shift_n = 276
 
 racc_action_table = [
-    75,    57,    61,   260,   179,    38,    40,    35,    44,   196,
-    54,   287,    45,   239,     3,     6,   187,   298,   240,  -145,
-    74,    75,    57,    61,   286,    47,    38,    40,   194,   195,
-   132,    49,    38,    40,   112,    60,    64,   194,   195,    70,
-    41,    74,   149,    43,    55,    77,   178,   118,    66,    48,
-   141,    87,    49,    75,    57,    61,    60,    64,    49,   109,
-    70,    41,   253,   123,    43,    55,    77,    41,   105,    66,
-    43,  -146,    87,    74,    75,    57,    61,   202,   151,   152,
-   153,   139,   140,   142,    49,   282,   128,   133,    60,    64,
-   201,   239,    70,   281,    74,   149,   240,    55,    77,   271,
-   118,    66,   179,   141,    87,    49,    75,    57,    61,    60,
-    64,    49,   193,    70,    35,   132,   123,   174,    55,    77,
-   192,     3,    66,    35,   258,    87,    74,    75,    57,    61,
-     3,   151,   152,   153,   139,   140,   142,    49,   116,    35,
-   155,    60,    64,   153,   139,    70,     3,    74,   149,  -147,
-    55,    77,  -143,   118,    66,   156,   141,    87,    49,    75,
-    57,    61,    60,    64,    49,   157,    70,   153,   139,   123,
-   134,    55,    77,    57,    61,    66,    33,    34,    87,    74,
-    75,    57,    61,   132,   151,   152,   153,   139,   140,   142,
-    49,  -145,   203,   274,    60,    64,   187,   188,    70,   275,
-    74,   149,  -142,    55,    77,  -144,   118,    66,    45,   141,
-    87,    49,    75,    57,    61,    60,    64,    49,    44,    70,
-    57,    61,   123,  -142,    55,    77,  -159,   128,    66,   177,
-   181,    87,    74,    75,    57,    61,  -143,   151,   152,   153,
-   139,   140,   142,    49,   116,   198,   278,    60,    64,   194,
-   195,    70,   248,    74,   186,  -145,    55,    77,   187,   188,
-    66,   216,   183,    87,    49,   187,   217,  -142,    60,    64,
-   150,   283,    70,   151,   152,   153,   139,    55,    77,   145,
-   149,    66,   284,   285,    87,   190,   105,   290,   141,   143,
-   146,   148,   101,   190,    75,    57,    61,   151,   152,   153,
-   139,   140,   142,   151,   152,   153,   139,   140,   142,   116,
-    98,    97,   144,   147,    74,  -142,   151,   152,   153,   139,
-   140,   142,  -144,  -143,  -147,    49,    75,    57,    61,    60,
-    64,  -144,   246,    70,   151,   152,   153,   139,    55,    77,
-   244,   278,    66,   301,   302,    87,    74,    75,    57,    61,
-  -144,   179,  -145,  -148,    73,   190,  -143,    49,   310,  -192,
-    37,    60,    64,  -147,  -146,    70,   292,    74,   nil,   nil,
-    55,    77,   nil,   nil,    66,   nil,   nil,    87,    49,    75,
-    57,    61,    60,    64,   nil,   nil,    70,   nil,   nil,   nil,
-   nil,    55,    77,   nil,   nil,    66,   nil,   nil,    87,    74,
-    75,    57,    61,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-    49,   nil,   nil,   nil,    60,    64,   nil,   nil,    70,   nil,
-    74,   nil,   nil,    55,    77,   nil,   nil,    66,   nil,   nil,
-    87,    49,    75,    57,    61,    60,    64,   nil,   nil,    70,
-   nil,   nil,   nil,   nil,    55,    77,   nil,   nil,    66,   nil,
-   nil,    87,    74,    75,    57,    61,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,    49,   nil,   nil,   nil,    60,    64,   nil,
-   nil,    70,   nil,    74,   nil,   nil,    55,    77,   nil,   nil,
-    66,   nil,   nil,    87,    49,    75,    57,    61,    60,    64,
-   nil,   nil,    70,   nil,   nil,   nil,   nil,    55,    77,   nil,
-   nil,    66,   nil,   nil,    87,    74,    75,    57,    61,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,    49,    75,    57,    61,
-    60,    64,   nil,   nil,    70,   nil,    74,   nil,   nil,    55,
-    77,   nil,   nil,    66,   nil,   nil,    87,    49,    75,    57,
-    61,    60,    64,   nil,   nil,    70,   nil,   nil,    49,   nil,
-    55,    77,    60,    64,    66,   nil,    70,    87,    74,   nil,
-   nil,    55,   nil,   nil,   nil,    66,   nil,   nil,   nil,    49,
-    54,    57,    61,    60,    64,   nil,   nil,    70,   nil,   nil,
-   nil,   nil,    55,    77,   nil,   nil,    66,   nil,   nil,    87,
-    51,    75,    57,    61,   nil,   nil,   nil,    75,    57,    61,
-   nil,    49,   nil,   nil,   nil,    60,    64,   nil,   nil,    70,
-   nil,   nil,   nil,    52,    55,    75,    57,    61,    66,   nil,
-   nil,   nil,    49,   nil,   nil,   nil,    60,   168,    49,   nil,
-    70,   nil,    60,   209,   nil,   161,    70,   nil,   nil,    66,
-   nil,   161,   nil,   nil,   nil,    66,    49,   nil,   nil,   nil,
-    60,    64,   nil,   nil,    70,    75,    57,    61,   137,    55,
-   nil,   nil,   nil,    66,   nil,    75,    57,    61,   nil,   nil,
-   nil,    75,    57,    61,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,    75,    57,    61,   nil,   nil,    49,    75,    57,    61,
-    60,    64,   nil,   nil,    70,   nil,    49,   nil,   nil,    55,
-    60,    64,    49,    66,    70,   nil,    60,    64,   nil,    55,
-    70,   nil,    49,    66,   nil,    55,    60,    64,    49,    66,
-    70,   nil,    60,    64,   nil,    55,    70,   nil,   nil,    66,
-   nil,    55,    75,    57,    61,    66,   nil,   nil,    75,    57,
-    61,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    75,    57,
-    61,   nil,   nil,   nil,   nil,    57,    61,   nil,   nil,   nil,
-   nil,   nil,   nil,    49,   nil,    57,    61,    60,    64,    49,
-   nil,    70,   nil,    60,    64,   nil,    55,    70,   nil,    49,
-    66,   nil,    55,    60,    64,    49,    66,    70,   nil,    60,
-   209,   nil,    55,    70,   nil,    49,    66,   nil,   161,    60,
-   209,   nil,    66,    70,    57,    61,    57,    61,   161,   nil,
-   nil,   nil,    66,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-    57,    61,    57,    61,   270,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,    49,   nil,    49,   nil,    60,    64,
-    60,   209,    70,   nil,    70,   nil,    52,    55,   nil,   161,
-    49,    66,    49,    66,    60,   209,    60,    64,    70,   nil,
-    70,    57,    61,   161,    52,    55,   nil,    66,   nil,    66,
-   nil,    57,    61,   nil,   nil,   280,   nil,    57,    61,   nil,
-   nil,   130,   nil,   nil,   nil,   nil,   nil,    57,    61,   nil,
-   nil,    49,   nil,   nil,   nil,    60,    64,    57,    61,    70,
-   210,    49,   nil,    52,    55,    60,   209,    49,    66,    70,
-   nil,    60,   209,   nil,   161,    70,   nil,    49,    66,   nil,
-   161,    60,   209,   nil,    66,    70,   nil,    49,    57,    61,
-   161,    60,   209,   nil,    66,    70,   nil,   nil,   nil,   nil,
-   161,   nil,   nil,   nil,    66,   145,   149,   nil,   205,   nil,
-   nil,   nil,   nil,   nil,   141,   143,   146,   148,    49,   nil,
-   nil,   nil,    60,    64,   nil,   nil,    70,   nil,   nil,   nil,
-    52,    55,   nil,   nil,   nil,    66,   nil,   nil,   144,   147,
-   145,   149,   151,   152,   153,   139,   140,   142,   215,   141,
-   143,   146,   148,   145,   149,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   141,   143,   146,   148,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   144,   147,   145,   149,   151,   152,   153,
-   139,   140,   142,   nil,   141,   143,   146,   148,   145,   149,
-   151,   152,   153,   139,   140,   142,   nil,   141,   143,   146,
-   148,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   147,
-   289,   nil,   151,   152,   153,   139,   140,   142,   nil,   nil,
-   nil,   144,   147,   nil,   nil,   151,   152,   153,   139,   140,
-   142,    16,   294,    23,    26,   nil,     1,     4,   nil,     9,
-   nil,    13,   nil,    20,   nil,    27,   nil,   nil,     3,     6,
-   nil,   295,   nil,    16,   nil,    23,    26,   nil,     1,     4,
-   nil,     9,   nil,    13,   nil,    20,   nil,    27,   nil,   nil,
-     3,     6,    16,   276,    23,    26,   nil,     1,     4,   nil,
-     9,   nil,    13,   nil,    20,   nil,    27,   nil,   nil,     3,
-     6,   nil,   307,   nil,    16,   nil,    23,    26,   nil,     1,
-     4,   nil,     9,   nil,    13,   nil,    20,   nil,    27,   nil,
-   nil,     3,     6,    16,   230,    23,    26,   nil,     1,     4,
-   nil,     9,   nil,    13,   nil,    20,   nil,    27,   nil,   nil,
-     3,     6,   nil,   312,   nil,    16,   nil,    23,    26,   nil,
-     1,     4,   nil,     9,   nil,    13,   nil,    20,   nil,    27,
-   nil,   nil,     3,     6,    16,   314,    23,    26,   nil,     1,
-     4,   nil,     9,   nil,    13,   nil,    20,   nil,    27,   nil,
-   nil,     3,     6,   nil,   256,   nil,    16,   nil,    23,    26,
-   nil,     1,     4,   nil,     9,   nil,    13,   nil,    20,   nil,
-    27,   nil,   nil,     3,     6,    16,   315,    23,    26,   nil,
-     1,     4,   nil,     9,   nil,    13,   nil,    20,   nil,    27,
-   nil,   nil,     3,     6,   nil,   250,   nil,    16,   nil,    23,
-    26,   nil,     1,     4,   nil,     9,   nil,    13,   nil,    20,
-   nil,    27,   nil,   nil,     3,     6,    16,   316,    23,    26,
-   nil,     1,     4,   nil,     9,   nil,    13,   nil,    20,   nil,
-    27,   nil,   nil,     3,     6,   nil,   nil,   nil,    16,   nil,
-    23,    26,   nil,     1,     4,   nil,     9,   nil,    13,   nil,
-    20,   nil,    27,   nil,   nil,     3,     6,    16,   nil,    23,
-    26,   nil,     1,     4,   nil,     9,   nil,    13,   nil,    20,
-   nil,    27,   nil,   nil,     3,     6,    16,   nil,    23,    26,
-   nil,     1,     4,   nil,     9,   nil,    13,   nil,    20,   nil,
-    27,   nil,   nil,     3,     6 ]
+    71,    51,    53,   184,   162,   102,    71,    51,    53,   132,
+   149,     5,   209,    47,  -127,    87,    71,    51,    53,    88,
+   208,    65,    71,    51,    53,   162,   144,    34,    35,    99,
+    65,    89,   126,  -127,    50,    54,    65,   126,    59,  -123,
+    50,    54,   207,    45,    59,   161,    65,    56,  -126,    45,
+    50,    54,    65,    56,    59,    90,    50,    54,   185,    45,
+    59,    36,   169,    56,    37,    45,    71,    51,    53,    56,
+   204,   206,    47,    51,    53,   200,   149,    51,    53,    33,
+   199,  -122,    71,    51,    53,   238,     1,    65,    71,    51,
+    53,    67,   144,    34,    35,    87,    65,   237,   234,  -123,
+    50,    54,    65,   200,    59,   233,    50,    54,   199,    45,
+    59,   252,    65,    56,    43,    45,    50,    54,    65,    56,
+    59,    33,    50,    54,   156,    45,    59,    36,     1,    56,
+    37,    45,    71,    51,    53,    56,   204,   206,    71,    51,
+    53,   149,   149,    34,    35,   188,   259,   196,    71,    51,
+    53,  -125,    65,    65,    71,    51,    53,   144,   144,    51,
+    53,   202,    65,   162,    33,   168,    50,    54,    65,   137,
+    59,     1,    50,    54,   168,    45,    59,    36,    65,    56,
+    37,    45,    50,   174,    65,    56,    59,  -122,    50,    54,
+   165,   111,    59,  -125,  -122,    56,   127,    45,    71,    51,
+    53,    56,    33,   211,    71,    51,    53,   204,   206,     1,
+     5,   135,   218,   186,    71,    51,    53,   188,   189,   106,
+   125,    51,    53,   221,   222,   231,   140,   140,    65,   225,
+   126,  -124,    50,    54,    65,   228,    59,    47,    50,    54,
+  -139,    45,    59,   123,    65,    56,   106,    45,    50,   112,
+    65,    56,    59,  -124,    50,   174,   134,   111,    59,    51,
+    53,    56,   164,   111,   239,    51,    53,    56,   240,   241,
+   242,  -124,    96,   140,  -126,    51,    53,    93,   179,   168,
+    91,    51,    53,   159,   181,   260,   262,    85,    65,   157,
+    88,   133,    50,   174,    65,    41,    59,  -124,    50,    54,
+   128,   111,    59,  -122,    65,    56,    43,    45,    50,   174,
+    65,    56,    59,  -125,    50,    54,  -123,   111,    59,    51,
+    53,    56,    43,    45,  -127,    51,    53,    56,   176,    40,
+   269,  -171,   270,  -128,  -123,    51,    53,   152,  -125,   nil,
+   nil,    51,    53,   nil,   nil,   nil,   nil,   nil,    65,   nil,
+   nil,   nil,    50,   174,    65,   nil,    59,   nil,    50,   174,
+    43,   111,    59,   nil,    65,    56,   nil,   111,    50,   174,
+    65,    56,    59,   254,    50,   174,   nil,   111,    59,    51,
+    53,    56,   nil,   111,   nil,    51,    53,    56,   nil,   nil,
+   nil,   nil,   nil,    15,   nil,    19,    21,   nil,    28,     2,
+   nil,     8,   nil,    13,   nil,    17,   nil,    22,    65,   nil,
+     1,     5,    50,   174,    65,   264,    59,   nil,    50,   174,
+   nil,   111,    59,   nil,   nil,    56,   nil,   111,   nil,   nil,
+   nil,    56,   nil,   nil,   271,    15,   nil,    19,    21,   nil,
+    28,     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,
+   nil,   nil,     1,     5,    15,   212,    19,    21,   nil,    28,
+     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,   nil,
+   nil,     1,     5,   nil,   230,    15,   nil,    19,    21,   nil,
+    28,     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,
+   nil,   nil,     1,     5,    15,   253,    19,    21,   nil,    28,
+     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,   nil,
+   nil,     1,     5,   nil,   214,    15,   nil,    19,    21,   nil,
+    28,     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,
+   nil,   nil,     1,     5,    15,   274,    19,    21,   nil,    28,
+     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,   nil,
+   nil,     1,     5,   nil,   235,    15,   nil,    19,    21,   nil,
+    28,     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,
+   nil,   nil,     1,     5,    15,   275,    19,    21,   nil,    28,
+     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,   nil,
+   nil,     1,     5,   nil,   nil,    15,   nil,    19,    21,   nil,
+    28,     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,
+   nil,   nil,     1,     5,    15,   nil,    19,    21,   nil,    28,
+     2,   nil,     8,   nil,    13,   nil,    17,   nil,    22,   nil,
+   nil,     1,     5,    15,   nil,    19,    21,   nil,    28,     2,
+   nil,     8,   nil,    13,   nil,    17,   nil,    22,   nil,   nil,
+     1,     5,    15,   nil,    19,    21,   nil,    28,     2,   nil,
+     8,   nil,    13,   nil,    17,   nil,    22,   nil,   nil,     1,
+     5,    15,   nil,    19,    21,   nil,    28,     2,   nil,     8,
+   nil,    13,   nil,    17,   nil,    22,   nil,   nil,     1,     5 ]
 
 racc_action_check = [
-    34,    34,    34,   191,   105,   112,   112,    17,    11,   125,
-    64,   242,    11,   287,    17,    17,   273,   273,   287,   263,
-    34,   153,   153,   153,   242,    11,     9,     9,   191,   191,
-    64,    34,   109,   109,    39,    34,    34,   125,   125,    34,
-   112,   153,   222,   112,    34,    34,   105,    48,    34,    11,
-   222,    34,   153,   139,   139,   139,   153,   153,    48,    39,
-   153,     9,   180,    48,     9,   153,   153,   109,   181,   153,
-   109,    69,   153,   139,   140,   140,   140,   129,   222,   222,
-   222,   222,   222,   222,   139,   236,   204,    68,   139,   139,
-   129,   157,   139,   236,   140,   227,   157,   139,   139,   204,
-   197,   139,   168,   227,   139,   140,   151,   151,   151,   140,
-   140,   197,   120,   140,   101,   168,   197,   101,   140,   140,
-   120,   101,   140,    26,   189,   140,   151,   141,   141,   141,
-    26,   227,   227,   227,   227,   227,   227,   151,   190,     4,
-    93,   151,   151,   232,   232,   151,     4,   141,   225,    67,
-   151,   151,    65,   118,   151,    94,   225,   151,   141,    77,
-    77,    77,   141,   141,   118,    96,   141,   231,   231,   118,
-    73,   141,   141,    23,    23,   141,     1,     1,   141,    77,
-   142,   142,   142,   209,   225,   225,   225,   225,   225,   225,
-    77,    62,   131,   211,    77,    77,   131,   131,    77,   217,
-   142,   224,    78,    77,    77,   173,    47,    77,    90,   224,
-    77,   142,    16,    16,    16,   142,   142,    47,    59,   142,
-   156,   156,    47,    58,   142,   142,    55,    50,   142,   102,
-   106,   142,    16,    74,    74,    74,   167,   224,   224,   224,
-   224,   224,   224,    16,    45,   127,   230,    16,    16,   127,
-   127,    16,   166,    74,   113,   165,    16,    16,   113,   113,
-    16,   136,   110,    16,    74,   136,   136,   163,    74,    74,
-    84,   239,    74,   221,   221,   221,   221,    74,    74,    84,
-    84,    74,   240,   241,    74,   162,    37,   245,    84,    84,
-    84,    84,    36,   115,    87,    87,    87,   220,   220,   220,
-   220,   220,   220,   228,   228,   228,   228,   228,   228,   248,
-    30,    27,    84,    84,    87,   262,    84,    84,    84,    84,
-    84,    84,    72,   264,   265,    87,   149,   149,   149,    87,
-    87,   267,   160,    87,   219,   219,   219,   219,    87,    87,
-   158,   276,    87,   278,   281,    87,   149,   148,   148,   148,
-    89,   116,    79,    80,    15,   293,    81,   149,   297,   298,
-     7,   149,   149,    83,    85,   149,   247,   148,   nil,   nil,
-   149,   149,   nil,   nil,   149,   nil,   nil,   149,   148,   143,
-   143,   143,   148,   148,   nil,   nil,   148,   nil,   nil,   nil,
-   nil,   148,   148,   nil,   nil,   148,   nil,   nil,   148,   143,
-   144,   144,   144,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   143,   nil,   nil,   nil,   143,   143,   nil,   nil,   143,   nil,
-   144,   nil,   nil,   143,   143,   nil,   nil,   143,   nil,   nil,
-   143,   144,    33,    33,    33,   144,   144,   nil,   nil,   144,
-   nil,   nil,   nil,   nil,   144,   144,   nil,   nil,   144,   nil,
-   nil,   144,    33,   152,   152,   152,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,    33,   nil,   nil,   nil,    33,    33,   nil,
-   nil,    33,   nil,   152,   nil,   nil,    33,    33,   nil,   nil,
-    33,   nil,   nil,    33,   152,   147,   147,   147,   152,   152,
-   nil,   nil,   152,   nil,   nil,   nil,   nil,   152,   152,   nil,
-   nil,   152,   nil,   nil,   152,   147,   146,   146,   146,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   147,    44,    44,    44,
-   147,   147,   nil,   nil,   147,   nil,   146,   nil,   nil,   147,
-   147,   nil,   nil,   147,   nil,   nil,   147,   146,   145,   145,
-   145,   146,   146,   nil,   nil,   146,   nil,   nil,    44,   nil,
-   146,   146,    44,    44,   146,   nil,    44,   146,   145,   nil,
-   nil,    44,   nil,   nil,   nil,    44,   nil,   nil,   nil,   145,
-    13,    13,    13,   145,   145,   nil,   nil,   145,   nil,   nil,
-   nil,   nil,   145,   145,   nil,   nil,   145,   nil,   nil,   145,
-    13,    98,    98,    98,   nil,   nil,   nil,   246,   246,   246,
-   nil,    13,   nil,   nil,   nil,    13,    13,   nil,   nil,    13,
-   nil,   nil,   nil,    13,    13,   274,   274,   274,    13,   nil,
-   nil,   nil,    98,   nil,   nil,   nil,    98,    98,   246,   nil,
-    98,   nil,   246,   246,   nil,    98,   246,   nil,   nil,    98,
-   nil,   246,   nil,   nil,   nil,   246,   274,   nil,   nil,   nil,
-   274,   274,   nil,   nil,   274,    75,    75,    75,    75,   274,
-   nil,   nil,   nil,   274,   nil,    54,    54,    54,   nil,   nil,
-   nil,   284,   284,   284,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,   178,   178,   178,   nil,   nil,    75,    20,    20,    20,
-    75,    75,   nil,   nil,    75,   nil,    54,   nil,   nil,    75,
-    54,    54,   284,    75,    54,   nil,   284,   284,   nil,    54,
-   284,   nil,   178,    54,   nil,   284,   178,   178,    20,   284,
-   178,   nil,    20,    20,   nil,   178,    20,   nil,   nil,   178,
-   nil,    20,   179,   179,   179,    20,   nil,   nil,   283,   283,
-   283,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   185,   185,
-   185,   nil,   nil,   nil,   nil,   193,   193,   nil,   nil,   nil,
-   nil,   nil,   nil,   179,   nil,   192,   192,   179,   179,   283,
-   nil,   179,   nil,   283,   283,   nil,   179,   283,   nil,   185,
-   179,   nil,   283,   185,   185,   193,   283,   185,   nil,   193,
-   193,   nil,   185,   193,   nil,   192,   185,   nil,   193,   192,
-   192,   nil,   193,   192,   202,   202,   210,   210,   192,   nil,
-   nil,   nil,   192,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   282,   282,   128,   128,   202,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,   202,   nil,   210,   nil,   202,   202,
-   210,   210,   202,   nil,   210,   nil,   202,   202,   nil,   210,
-   282,   202,   128,   210,   282,   282,   128,   128,   282,   nil,
-   128,    51,    51,   282,   128,   128,   nil,   282,   nil,   128,
-   nil,   234,   234,   nil,   nil,   234,   nil,   296,   296,   nil,
-   nil,    51,   nil,   nil,   nil,   nil,   nil,   155,   155,   nil,
-   nil,    51,   nil,   nil,   nil,    51,    51,   133,   133,    51,
-   133,   234,   nil,    51,    51,   234,   234,   296,    51,   234,
-   nil,   296,   296,   nil,   234,   296,   nil,   155,   234,   nil,
-   296,   155,   155,   nil,   296,   155,   nil,   133,   132,   132,
-   155,   133,   133,   nil,   155,   133,   nil,   nil,   nil,   nil,
-   133,   nil,   nil,   nil,   133,   100,   100,   nil,   132,   nil,
-   nil,   nil,   nil,   nil,   100,   100,   100,   100,   132,   nil,
-   nil,   nil,   132,   132,   nil,   nil,   132,   nil,   nil,   nil,
-   132,   132,   nil,   nil,   nil,   132,   nil,   nil,   100,   100,
-   135,   135,   100,   100,   100,   100,   100,   100,   135,   135,
-   135,   135,   135,   226,   226,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   226,   226,   226,   226,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   135,   135,   223,   223,   135,   135,   135,
-   135,   135,   135,   nil,   223,   223,   223,   223,    99,    99,
-   226,   226,   226,   226,   226,   226,   nil,    99,    99,    99,
-    99,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   223,
-   244,   nil,   223,   223,   223,   223,   223,   223,   nil,   nil,
-   nil,    99,    99,   nil,   nil,    99,    99,    99,    99,    99,
-    99,   244,   249,   244,   244,   nil,   244,   244,   nil,   244,
-   nil,   244,   nil,   244,   nil,   244,   nil,   nil,   244,   244,
-   nil,   255,   nil,   249,   nil,   249,   249,   nil,   249,   249,
-   nil,   249,   nil,   249,   nil,   249,   nil,   249,   nil,   nil,
-   249,   249,   255,   229,   255,   255,   nil,   255,   255,   nil,
-   255,   nil,   255,   nil,   255,   nil,   255,   nil,   nil,   255,
-   255,   nil,   288,   nil,   229,   nil,   229,   229,   nil,   229,
-   229,   nil,   229,   nil,   229,   nil,   229,   nil,   229,   nil,
-   nil,   229,   229,   288,   150,   288,   288,   nil,   288,   288,
-   nil,   288,   nil,   288,   nil,   288,   nil,   288,   nil,   nil,
-   288,   288,   nil,   301,   nil,   150,   nil,   150,   150,   nil,
-   150,   150,   nil,   150,   nil,   150,   nil,   150,   nil,   150,
-   nil,   nil,   150,   150,   301,   302,   301,   301,   nil,   301,
-   301,   nil,   301,   nil,   301,   nil,   301,   nil,   301,   nil,
-   nil,   301,   301,   nil,   183,   nil,   302,   nil,   302,   302,
-   nil,   302,   302,   nil,   302,   nil,   302,   nil,   302,   nil,
-   302,   nil,   nil,   302,   302,   183,   311,   183,   183,   nil,
-   183,   183,   nil,   183,   nil,   183,   nil,   183,   nil,   183,
-   nil,   nil,   183,   183,   nil,   177,   nil,   311,   nil,   311,
-   311,   nil,   311,   311,   nil,   311,   nil,   311,   nil,   311,
-   nil,   311,   nil,   nil,   311,   311,   177,   313,   177,   177,
-   nil,   177,   177,   nil,   177,   nil,   177,   nil,   177,   nil,
-   177,   nil,   nil,   177,   177,   nil,   nil,   nil,   313,   nil,
-   313,   313,   nil,   313,   313,   nil,   313,   nil,   313,   nil,
-   313,   nil,   313,   nil,   nil,   313,   313,    19,   nil,    19,
-    19,   nil,    19,    19,   nil,    19,   nil,    19,   nil,    19,
-   nil,    19,   nil,   nil,    19,    19,     0,   nil,     0,     0,
-   nil,     0,     0,   nil,     0,   nil,     0,   nil,     0,   nil,
-     0,   nil,   nil,     0,     0 ]
+    93,    93,    93,   127,   106,    38,    71,    71,    71,    71,
+    90,   127,   146,    54,    78,    23,    87,    87,    87,    23,
+   146,    90,   161,   161,   161,   112,    90,   102,   102,    38,
+    93,    23,    54,    64,    93,    93,    71,   112,    93,    62,
+    71,    71,   142,    93,    71,   106,    87,    93,    66,    71,
+    87,    87,   161,    71,    87,    23,   161,   161,   129,    87,
+   161,   102,   119,    87,   102,   161,   240,   240,   240,   161,
+   142,   142,    13,    13,    13,   238,   149,   135,   135,     2,
+   238,    74,    15,    15,    15,   197,     2,   149,    17,    17,
+    17,    13,   149,    99,    99,    61,   240,   197,   194,   118,
+   240,   240,    13,   137,   240,   194,    13,    13,   137,   240,
+    13,   210,    15,   240,    13,    13,    15,    15,    17,    13,
+    15,    96,    17,    17,    96,    15,    17,    99,    96,    15,
+    99,    17,   239,   239,   239,    17,   210,   210,   162,   162,
+   162,    89,   205,     8,     8,   227,   227,   136,   165,   165,
+   165,   116,    89,   205,    47,    47,    47,    89,   205,    19,
+    19,   139,   239,   140,    21,   141,   239,   239,   162,    84,
+   239,    21,   162,   162,   115,   239,   162,     8,   165,   239,
+     8,   162,   165,   165,    47,   162,   165,   114,    47,    47,
+   113,   165,    47,    60,    58,   165,    55,    47,   225,   225,
+   225,    47,    29,   151,   187,   187,   187,   151,   151,    29,
+    29,    83,   163,   131,    41,    41,    41,   131,   131,   164,
+    52,   192,   192,   166,   167,   192,   168,   169,   225,   170,
+   174,    46,   225,   225,   187,   182,   225,   184,   187,   187,
+    45,   225,   187,    42,    41,   225,    40,   187,    41,    41,
+   192,   187,    41,   110,   192,   192,    81,    41,   192,   208,
+   208,    41,   107,   192,   199,   126,   126,   192,   200,   201,
+   203,    70,    32,    88,    79,   209,   209,    28,   124,   224,
+    25,    67,    67,   100,   126,   230,   233,    22,   208,    97,
+    95,    73,   208,   208,   126,    11,   208,   245,   126,   126,
+    67,   208,   126,   246,   209,   208,   126,   126,   209,   209,
+    67,   126,   209,   248,    67,    67,   249,   209,    67,   125,
+   125,   209,    67,    67,   250,   123,   123,    67,   123,     9,
+   258,   259,   260,    77,    76,   176,   176,    91,    75,   nil,
+   nil,   134,   134,   nil,   nil,   nil,   nil,   nil,   125,   nil,
+   nil,   nil,   125,   125,   123,   nil,   125,   nil,   123,   123,
+   125,   125,   123,   nil,   176,   125,   nil,   123,   176,   176,
+   134,   123,   176,   215,   134,   134,   nil,   176,   134,   234,
+   234,   176,   nil,   134,   nil,   257,   257,   134,   nil,   nil,
+   nil,   nil,   nil,   215,   nil,   215,   215,   nil,   215,   215,
+   nil,   215,   nil,   215,   nil,   215,   nil,   215,   234,   nil,
+   215,   215,   234,   234,   257,   236,   234,   nil,   257,   257,
+   nil,   234,   257,   nil,   nil,   234,   nil,   257,   nil,   nil,
+   nil,   257,   nil,   nil,   262,   236,   nil,   236,   236,   nil,
+   236,   236,   nil,   236,   nil,   236,   nil,   236,   nil,   236,
+   nil,   nil,   236,   236,   262,   157,   262,   262,   nil,   262,
+   262,   nil,   262,   nil,   262,   nil,   262,   nil,   262,   nil,
+   nil,   262,   262,   nil,   190,   157,   nil,   157,   157,   nil,
+   157,   157,   nil,   157,   nil,   157,   nil,   157,   nil,   157,
+   nil,   nil,   157,   157,   190,   213,   190,   190,   nil,   190,
+   190,   nil,   190,   nil,   190,   nil,   190,   nil,   190,   nil,
+   nil,   190,   190,   nil,   159,   213,   nil,   213,   213,   nil,
+   213,   213,   nil,   213,   nil,   213,   nil,   213,   nil,   213,
+   nil,   nil,   213,   213,   159,   272,   159,   159,   nil,   159,
+   159,   nil,   159,   nil,   159,   nil,   159,   nil,   159,   nil,
+   nil,   159,   159,   nil,   196,   272,   nil,   272,   272,   nil,
+   272,   272,   nil,   272,   nil,   272,   nil,   272,   nil,   272,
+   nil,   nil,   272,   272,   196,   273,   196,   196,   nil,   196,
+   196,   nil,   196,   nil,   196,   nil,   196,   nil,   196,   nil,
+   nil,   196,   196,   nil,   nil,   273,   nil,   273,   273,   nil,
+   273,   273,   nil,   273,   nil,   273,   nil,   273,   nil,   273,
+   nil,   nil,   273,   273,   133,   nil,   133,   133,   nil,   133,
+   133,   nil,   133,   nil,   133,   nil,   133,   nil,   133,   nil,
+   nil,   133,   133,   270,   nil,   270,   270,   nil,   270,   270,
+   nil,   270,   nil,   270,   nil,   270,   nil,   270,   nil,   nil,
+   270,   270,    27,   nil,    27,    27,   nil,    27,    27,   nil,
+    27,   nil,    27,   nil,    27,   nil,    27,   nil,   nil,    27,
+    27,     0,   nil,     0,     0,   nil,     0,     0,   nil,     0,
+   nil,     0,   nil,     0,   nil,     0,   nil,   nil,     0,     0 ]
 
 racc_action_pointer = [
-  1308,   163,   nil,   nil,   101,   nil,   nil,   354,   nil,    23,
-   nil,     6,   nil,   568,   nil,   354,   210,   -31,   nil,  1289,
-   685,   nil,   nil,   170,   nil,   nil,    85,   269,   nil,   nil,
-   304,   nil,   nil,   430,    -2,   nil,   257,   248,   nil,    24,
-   nil,   nil,   nil,   nil,   515,   206,   nil,   184,    25,   nil,
-   217,   858,   nil,   nil,   663,   224,   nil,   nil,   202,   216,
-   nil,   nil,   170,   nil,     8,   131,   nil,   128,    66,    50,
-   nil,   nil,   301,   170,   231,   653,   nil,   157,   181,   331,
-   332,   335,   nil,   342,   264,   343,   nil,   292,   nil,   329,
-   202,   nil,   nil,   134,   145,   nil,   143,   nil,   589,  1013,
-   930,    76,   223,   nil,   nil,    -5,   220,   nil,   nil,    29,
-   256,   nil,     2,   249,   nil,   283,   342,   nil,   131,   nil,
-    96,   nil,   nil,   nil,   nil,   -11,   nil,   201,   819,    67,
-   nil,   187,   925,   894,   nil,   965,   256,   nil,   nil,    51,
-    72,   125,   178,   377,   398,   536,   504,   483,   345,   324,
-  1147,   104,   451,    19,   nil,   884,   217,    58,   334,   nil,
-   293,   nil,   275,   246,   nil,   234,   234,   215,    93,   nil,
-   nil,   nil,   nil,   184,   nil,   nil,   nil,  1248,   679,   730,
-    55,    30,   nil,  1207,   nil,   746,   nil,   nil,   nil,   117,
-   100,   -20,   762,   752,   nil,   nil,   nil,    78,   nil,   nil,
-   nil,   nil,   801,   nil,    76,   nil,   nil,   nil,   nil,   161,
-   803,   184,   nil,   nil,   nil,   nil,   nil,   194,   nil,   282,
-   245,   221,    26,  1000,   185,   132,   978,    79,   251,  1106,
-   217,   113,    89,   nil,   868,   nil,    75,   nil,   nil,   258,
-   269,   260,     1,   nil,  1043,   280,   595,   359,   271,  1065,
-   nil,   nil,   nil,   nil,   nil,  1084,   nil,   nil,   nil,   nil,
-   nil,   nil,   294,    -2,   302,   303,   nil,   310,   nil,   nil,
-   nil,   nil,   nil,     7,   613,   nil,   312,   nil,   337,   nil,
-   nil,   338,   817,   736,   669,   nil,   nil,   -20,  1125,   nil,
-   nil,   nil,   nil,   345,   nil,   nil,   874,   351,   352,   nil,
-   nil,  1166,  1188,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,  1229,   nil,  1270,   nil,   nil,   nil ]
+   644,   nil,    42,   nil,   nil,   nil,   nil,   nil,   140,   323,
+   nil,   289,   nil,    70,   nil,    80,   nil,    86,   nil,   156,
+   nil,   127,   246,    13,   nil,   280,   nil,   625,   264,   165,
+   nil,   nil,   238,   nil,   nil,   nil,   nil,   nil,    -5,   nil,
+   209,   212,   223,   nil,   nil,   238,   211,   152,   nil,   nil,
+   nil,   nil,   210,   nil,    11,   186,   nil,   nil,   174,   nil,
+   173,    93,    19,   nil,    13,   nil,    28,   278,   nil,   nil,
+   251,     4,   nil,   285,    61,   318,   314,   313,    -6,   254,
+   nil,   250,   nil,   201,   148,   nil,   nil,    14,   236,   120,
+   -11,   337,   nil,    -2,   nil,   284,    84,   283,   nil,    90,
+   277,   nil,    24,   nil,   nil,   nil,    -5,   252,   nil,   nil,
+   233,   nil,    16,   152,   167,   164,   131,   nil,    79,    45,
+   nil,   nil,   nil,   322,   273,   316,   262,   -34,   nil,    36,
+   nil,   208,   nil,   587,   338,    74,   141,    71,   nil,   156,
+   154,   155,    23,   nil,   nil,   nil,    -3,   nil,   nil,    55,
+   nil,   160,   nil,   nil,   nil,   nil,   nil,   448,   nil,   507,
+   nil,    20,   136,   205,   182,   146,   216,   217,   189,   190,
+   220,   nil,   nil,   nil,   209,   nil,   332,   nil,   nil,   nil,
+   nil,   nil,   213,   nil,   235,   nil,   nil,   202,   nil,   nil,
+   467,   nil,   218,   nil,    88,   nil,   547,    75,   nil,   251,
+   255,   247,   nil,   263,   nil,   121,   nil,   nil,   256,   272,
+    89,   nil,   nil,   488,   nil,   366,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   269,   196,   nil,   136,   nil,   nil,
+   257,   nil,   nil,   280,   376,   nil,   408,   nil,    43,   130,
+    64,   nil,   nil,   nil,   nil,   277,   283,   nil,   293,   296,
+   304,   nil,   nil,   nil,   nil,   nil,   nil,   382,   323,   324,
+   326,   nil,   427,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   606,   nil,   528,   568,   nil,   nil ]
 
 racc_action_default = [
-  -168,  -193,    -7,  -161,  -193,    -8,  -159,  -193,    -9,  -193,
-   -10,  -193,   -11,  -160,   -12,  -193,  -193,  -193,   -13,    -1,
-  -193,   -14,    -2,  -193,   -15,    -3,  -193,   -39,   -16,    -5,
-  -193,   -17,    -6,  -193,  -193,  -160,  -168,   -78,  -166,  -168,
-  -165,  -164,  -162,  -167,  -193,   -71,   -41,  -168,  -168,  -185,
-   -21,  -193,   -33,   -22,  -193,   -62,   -23,  -101,   -26,  -193,
-  -103,  -102,   -27,  -148,   -61,   -28,   -60,   -29,  -193,   -30,
-  -149,   -31,   -32,  -193,  -193,  -193,   -96,  -193,   -90,   -94,
-   -98,   -91,   -95,   -92,  -193,   -97,   -93,  -193,  -111,   -89,
-  -193,   -38,    -4,  -193,  -152,  -150,  -168,   -40,   -71,   -69,
-   -70,  -193,  -193,  -181,   -79,  -193,  -191,   -76,   -77,  -193,
-  -193,  -179,  -193,  -193,   -81,  -191,  -193,   -72,  -168,   -47,
-  -193,   -54,   -53,   -61,   -44,  -193,   -45,  -193,  -193,  -193,
-   -20,  -193,  -193,  -193,   317,  -193,  -193,  -188,  -125,  -193,
-  -193,  -193,  -193,  -193,  -193,  -193,  -193,  -193,  -193,  -193,
-  -193,  -193,  -193,  -193,  -118,  -193,  -193,  -169,  -193,  -170,
-   -58,   -62,  -191,   -64,   -56,   -67,  -193,   -65,   -61,  -147,
-   -68,  -146,   -66,   -63,  -184,  -182,  -183,  -193,  -193,  -193,
-  -193,  -192,  -180,  -193,  -163,  -193,  -105,  -189,  -190,  -193,
-  -192,  -193,  -193,  -193,   -50,   -49,   -43,  -193,   -42,   -24,
-   -25,   -18,  -193,  -104,  -193,  -100,  -142,  -145,  -143,   -61,
-  -193,  -193,  -136,  -144,  -137,  -128,  -186,  -190,  -114,  -116,
-  -120,  -117,  -122,  -127,  -124,  -121,  -126,  -123,  -119,  -193,
-  -108,  -112,  -113,  -115,  -193,  -130,  -193,  -134,  -151,  -178,
-  -176,  -193,  -193,  -173,  -193,  -193,   -59,  -193,   -71,  -193,
-  -156,   -75,   -74,   -37,   -80,  -193,  -158,   -82,   -36,   -73,
-   -48,   -51,   -84,   -88,   -85,   -86,   -87,   -83,   -52,   -46,
-   -19,   -99,  -139,  -191,  -193,  -187,  -108,  -107,  -193,  -131,
-  -129,  -193,  -193,  -193,  -193,  -171,  -172,  -193,  -193,  -154,
-   -34,   -57,   -35,  -191,  -155,  -157,  -193,  -193,  -190,  -141,
-  -106,  -193,  -193,  -135,  -177,  -175,  -174,  -153,   -55,  -140,
-  -138,  -193,  -110,  -193,  -133,  -109,  -132 ]
+  -148,  -141,  -172,   -15,    -3,  -139,   -16,    -5,  -172,  -172,
+    -6,  -172,    -7,  -140,    -8,  -172,    -9,  -172,   -10,  -172,
+   -11,  -172,   -39,  -172,   -12,  -172,   -13,    -1,  -172,  -172,
+   -14,    -2,  -148,  -140,  -146,  -145,  -144,  -147,  -148,  -142,
+   -77,   -70,  -172,   -31,   -29,   -62,   -30,  -172,   -32,   -19,
+  -102,  -100,   -20,  -101,   -61,   -21,   -60,   -22,   -24,  -129,
+   -25,  -172,   -26,  -128,   -27,  -165,   -28,  -172,  -108,   -92,
+   -88,  -172,   -95,  -172,   -89,   -93,   -90,   -97,   -91,   -96,
+   -94,  -172,  -130,  -132,  -148,   -40,   -41,  -172,   -70,  -148,
+  -148,  -172,    -4,  -172,   -38,  -172,  -172,  -172,  -161,  -172,
+  -172,  -159,  -172,   -75,   -76,   -78,  -172,  -170,   -66,   -71,
+   -63,   -62,   -61,   -58,   -64,  -170,   -67,   -56,   -65,  -172,
+  -127,  -126,   -68,  -172,  -172,  -172,  -172,  -172,   -18,  -172,
+   -80,  -172,  -167,  -172,  -172,  -172,  -172,  -149,  -150,  -172,
+  -172,  -170,  -172,   -45,   -61,   -47,  -172,   -54,   -53,  -148,
+   -44,  -172,   276,   -69,  -162,  -163,  -164,  -172,  -160,  -172,
+  -143,  -172,  -172,  -172,  -171,   -59,  -172,  -172,  -171,   -70,
+  -172,  -124,  -116,  -117,   -61,  -122,  -172,  -125,  -123,  -103,
+   -23,   -99,  -172,   -33,  -172,   -17,  -166,  -172,  -168,  -169,
+  -172,  -114,  -172,  -110,  -172,  -131,  -172,  -172,  -153,  -156,
+  -158,  -172,  -104,  -172,   -50,  -172,   -49,   -43,  -172,  -172,
+  -172,   -42,  -136,  -172,  -138,  -172,   -74,   -73,   -37,   -79,
+   -57,   -34,   -35,   -72,  -170,  -172,  -119,  -170,   -98,   -81,
+  -106,  -109,  -111,  -172,  -172,  -134,  -172,  -152,  -172,  -172,
+  -172,  -151,   -36,   -46,   -86,   -82,   -83,   -51,   -87,   -84,
+   -85,   -52,   -48,  -135,  -137,   -55,  -121,  -172,  -172,  -169,
+  -172,  -105,  -172,  -115,  -133,  -154,  -155,  -157,  -120,  -118,
+  -172,  -113,  -172,  -172,  -112,  -107 ]
 
 racc_goto_table = [
-     7,    92,    65,    11,   214,   115,   180,    19,   170,   243,
-   107,   164,   211,    56,    50,   189,   104,    36,   235,     7,
-    90,    71,    11,    15,    42,   199,   277,    63,   261,   268,
-    22,   296,   125,   127,   237,   269,   113,   234,    46,    96,
-    65,   106,   212,   245,   273,    94,   131,   158,   102,    39,
-   110,    56,   129,   160,   241,   242,    91,   175,   162,    71,
-   nil,   nil,   247,   nil,   nil,    63,   103,   136,    93,   111,
-   nil,   nil,   300,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,   272,   nil,   nil,   nil,   nil,   nil,   167,   nil,   211,
-   nil,   nil,   114,   nil,   nil,   nil,   nil,   279,   nil,   199,
-    62,   nil,   114,   191,   nil,   nil,   172,   nil,   nil,   nil,
-   nil,   nil,    63,   237,   176,   nil,   nil,    65,   nil,   nil,
-   nil,    65,   208,   114,   182,   nil,   159,   184,   200,   nil,
-   nil,   nil,    56,   204,   122,   122,    71,   nil,    62,   306,
-    71,   nil,    63,   nil,   208,   nil,    63,    63,   nil,   nil,
-     7,   nil,   nil,    11,   107,   nil,   170,   229,    69,   291,
-   254,   303,   nil,   259,   nil,   nil,   nil,   309,   nil,    63,
-   nil,   nil,   nil,   297,   nil,   211,   nil,     7,   nil,   nil,
-    11,   264,   264,     7,   249,   165,    11,   nil,   nil,   nil,
-   255,    65,   nil,   308,   nil,   nil,    69,   nil,   nil,   208,
-   266,   266,   200,   nil,   nil,   122,    63,    63,   293,   nil,
-    71,    92,   nil,   nil,   nil,    62,    63,   nil,   nil,    62,
-   207,   nil,   nil,   208,    63,   nil,   251,   252,   nil,     7,
-   nil,    92,    11,   257,    58,   167,   nil,    92,   nil,   nil,
-   nil,   nil,   207,   171,     7,    67,   nil,    11,    63,     7,
-   nil,   288,    11,   nil,   172,     7,   nil,   nil,    11,   nil,
-    63,   nil,   nil,   nil,   nil,    72,   nil,   nil,   121,   121,
-    92,   208,    58,    69,   nil,    95,   nil,    69,   171,   263,
-   263,   nil,   nil,    67,   122,   208,   nil,   nil,     7,    62,
-   nil,    11,   nil,    92,   nil,    92,    63,   207,   nil,   nil,
-   171,     7,     7,    72,    11,    11,   nil,   nil,   311,   313,
-    63,     7,   nil,     7,    11,   nil,    11,   nil,   nil,   163,
-   nil,   207,   299,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   169,   304,   305,   165,   nil,   nil,   nil,   171,   171,   121,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,    69,   nil,    58,
-   173,   nil,   nil,    58,   206,   171,   nil,   nil,   nil,   nil,
-    67,   nil,   nil,   nil,    67,   169,   nil,   nil,   nil,   207,
-   nil,   nil,   nil,   nil,   nil,   nil,   206,   nil,   nil,   171,
-    72,   nil,   nil,   207,    72,   213,   nil,   169,   nil,   nil,
-   nil,   171,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   213,   238,   nil,
-   nil,   nil,   nil,   262,   262,   nil,   nil,   nil,   121,   nil,
-   nil,   nil,   nil,    58,   265,   265,   nil,   171,   nil,    84,
-   nil,   206,   nil,   nil,    67,   nil,   nil,   nil,   nil,   nil,
-   nil,   171,   169,   nil,   267,   267,    99,   100,   nil,   nil,
-   nil,   nil,   nil,   nil,    72,   206,   nil,   nil,   nil,   nil,
-   nil,   nil,   213,   nil,   nil,   nil,   169,   163,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   169,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   213,   135,   nil,   nil,
-   138,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   173,   nil,
-   154,   nil,   nil,   206,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,   169,   nil,   nil,   206,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   169,   nil,
-   nil,   nil,   nil,   nil,   213,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   213,   nil,
-   nil,   nil,   218,   219,   220,   221,   222,   223,   224,   225,
-   226,   227,   228,   nil,   231,   232,   233 ]
+    23,    27,   122,    92,   173,   105,   198,    49,   117,    46,
+   187,    39,    31,   170,    32,    82,   193,   103,   115,    25,
+   142,   151,   243,    44,   191,   247,   251,    23,   131,    95,
+    64,    86,    73,    84,   261,   192,   107,   110,   166,   172,
+   113,   227,    83,    62,    98,   163,   136,    97,    38,   100,
+   101,   108,   180,   167,   201,   197,    94,   226,   120,   154,
+   nil,   129,   nil,    46,    66,   141,   170,   nil,   nil,   nil,
+   nil,   118,   nil,   nil,   232,   nil,   nil,    44,   nil,   203,
+   210,   nil,   191,   nil,    64,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   121,   nil,   nil,   nil,   138,    62,   nil,   nil,
+   nil,   nil,   158,   nil,   nil,   160,   257,   265,   155,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    66,   171,
+   182,    46,    46,   nil,   263,   nil,   122,   nil,   nil,   219,
+   171,   195,   220,    23,   190,    44,    44,   nil,   268,   nil,
+   120,   103,    64,    64,   nil,   223,   224,   170,   nil,   nil,
+   nil,   120,   nil,   178,   nil,    62,    62,    23,   213,    23,
+   215,   110,   255,   nil,   178,   258,    92,   nil,   nil,   nil,
+    60,   nil,   171,   nil,   121,   108,    66,    66,   nil,   nil,
+    58,   nil,   120,   nil,   nil,   121,   nil,   nil,   171,    92,
+    23,    92,   nil,   120,   nil,   118,    23,   236,   116,   nil,
+   nil,   nil,   nil,   nil,   245,   245,   178,   nil,   114,   120,
+   nil,   nil,    92,    23,   nil,    23,   121,   nil,   244,   244,
+   nil,   nil,   178,   nil,    60,   250,   250,   121,   nil,   nil,
+   171,   nil,   nil,   nil,    58,   nil,    23,   nil,   249,   249,
+   nil,   nil,   nil,   121,   nil,   nil,   148,   148,    92,    92,
+   nil,   120,   nil,   171,   nil,   nil,   147,   147,   nil,   121,
+   121,   nil,    23,   272,   178,   nil,   nil,   nil,   nil,   nil,
+    23,   273,    23,    23,   120,    68,   nil,    81,   nil,    77,
+   177,    77,    60,    60,    48,   121,    72,   178,    72,   nil,
+   175,   177,    58,    58,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   175,   nil,   nil,   nil,   nil,   148,   124,   121,   nil,
+   nil,    77,   nil,   nil,   nil,   nil,   147,   nil,    72,   nil,
+   nil,   nil,   116,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   130,   114,   177,   nil,    77,   nil,   nil,    48,   nil,
+   nil,   nil,    72,   175,   nil,   nil,   nil,   139,   nil,   177,
+   nil,    77,   nil,   153,   nil,   nil,   nil,    77,    72,   175,
+   nil,   nil,   148,   nil,    72,   248,   248,   nil,   nil,   nil,
+   nil,   nil,   147,   nil,   nil,   246,   246,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   177,   nil,   nil,   nil,   nil,   nil,    48,   183,   nil,
+   nil,   175,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   177,   nil,   nil,   nil,   nil,   nil,
+   nil,   216,   217,   nil,   175,    77,    77,   nil,   nil,   nil,
+   nil,   nil,    72,    72,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   229,   nil,   nil,
+   nil,    77,   nil,   nil,   nil,   nil,   nil,   nil,    72,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   256,   nil,   nil,   nil,    77,
+   nil,   nil,   nil,   nil,   nil,   nil,    72,   nil,   nil,   266,
+   267,   nil,   nil,    77,    77,   nil,   nil,   nil,   nil,   nil,
+    72,    72 ]
 
 racc_goto_check = [
-    20,     4,    23,    33,    60,    31,    32,     2,    46,    70,
-    48,    43,    58,    20,    18,    32,    51,    28,    56,    20,
-    33,    26,    33,     1,    67,    19,    54,    45,    42,    42,
-     3,    53,    37,    37,    58,    38,    52,    55,    36,    28,
-    23,    34,    59,    30,    61,    62,    52,    63,    64,    65,
-    66,    20,    18,    29,    68,    69,     5,    71,    31,    26,
-   nil,   nil,    32,   nil,   nil,    45,     3,    52,    49,     3,
-   nil,   nil,    54,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,    60,   nil,   nil,   nil,   nil,   nil,    23,   nil,    58,
-   nil,   nil,    49,   nil,   nil,   nil,   nil,    56,   nil,    19,
-    22,   nil,    49,    37,   nil,   nil,    26,   nil,   nil,   nil,
-   nil,   nil,    45,    58,    28,   nil,   nil,    23,   nil,   nil,
-   nil,    23,    23,    49,    67,   nil,     3,    67,    20,   nil,
-   nil,   nil,    20,    18,    22,    22,    26,   nil,    22,    70,
-    26,   nil,    45,   nil,    23,   nil,    45,    45,   nil,   nil,
-    20,   nil,   nil,    33,    48,   nil,    46,     2,    25,    43,
-    51,    58,   nil,    48,   nil,   nil,   nil,    60,   nil,    45,
-   nil,   nil,   nil,    32,   nil,    58,   nil,    20,   nil,   nil,
-    33,    23,    23,    20,     2,    22,    33,   nil,   nil,   nil,
-     2,    23,   nil,    32,   nil,   nil,    25,   nil,   nil,    23,
-    26,    26,    20,   nil,   nil,    22,    45,    45,    31,   nil,
-    26,     4,   nil,   nil,   nil,    22,    45,   nil,   nil,    22,
-    22,   nil,   nil,    23,    45,   nil,    49,    49,   nil,    20,
-   nil,     4,    33,    49,    21,    23,   nil,     4,   nil,   nil,
-   nil,   nil,    22,    25,    20,    24,   nil,    33,    45,    20,
-   nil,     2,    33,   nil,    26,    20,   nil,   nil,    33,   nil,
-    45,   nil,   nil,   nil,   nil,    27,   nil,   nil,    21,    21,
-     4,    23,    21,    25,   nil,    27,   nil,    25,    25,    22,
-    22,   nil,   nil,    24,    22,    23,   nil,   nil,    20,    22,
-   nil,    33,   nil,     4,   nil,     4,    45,    22,   nil,   nil,
-    25,    20,    20,    27,    33,    33,   nil,   nil,     2,     2,
-    45,    20,   nil,    20,    33,   nil,    33,   nil,   nil,    21,
-   nil,    22,    49,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-    24,    49,    49,    22,   nil,   nil,   nil,    25,    25,    21,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,    25,   nil,    21,
-    27,   nil,   nil,    21,    21,    25,   nil,   nil,   nil,   nil,
-    24,   nil,   nil,   nil,    24,    24,   nil,   nil,   nil,    22,
-   nil,   nil,   nil,   nil,   nil,   nil,    21,   nil,   nil,    25,
-    27,   nil,   nil,    22,    27,    27,   nil,    24,   nil,   nil,
-   nil,    25,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,    27,    27,   nil,
-   nil,   nil,   nil,    21,    21,   nil,   nil,   nil,    21,   nil,
-   nil,   nil,   nil,    21,    24,    24,   nil,    25,   nil,    47,
-   nil,    21,   nil,   nil,    24,   nil,   nil,   nil,   nil,   nil,
-   nil,    25,    24,   nil,    27,    27,    47,    47,   nil,   nil,
-   nil,   nil,   nil,   nil,    27,    21,   nil,   nil,   nil,   nil,
-   nil,   nil,    27,   nil,   nil,   nil,    24,    21,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    24,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,    27,    47,   nil,   nil,
-    47,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    27,   nil,
-    47,   nil,   nil,    21,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,    24,   nil,   nil,    21,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    24,   nil,
-   nil,   nil,   nil,   nil,    27,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    27,   nil,
-   nil,   nil,    47,    47,    47,    47,    47,    47,    47,    47,
-    47,    47,    47,   nil,    47,    47,    47 ]
+    34,     2,    47,     4,    61,    51,    71,    17,    44,    27,
+    53,    68,     3,    59,    29,    27,    57,    49,    32,     1,
+    38,    38,    39,    26,    59,    43,    43,    34,    52,    34,
+    24,    37,    54,    29,    55,    56,    35,    27,    31,    60,
+    30,    62,    63,    23,     3,    33,    64,    65,    66,    67,
+     3,    26,    20,    33,    69,    70,     5,    61,    24,    72,
+   nil,    17,   nil,    27,    25,    32,    59,   nil,   nil,   nil,
+   nil,    23,   nil,   nil,    57,   nil,   nil,    26,   nil,    33,
+    38,   nil,    59,   nil,    24,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,    25,   nil,   nil,   nil,     3,    23,   nil,   nil,
+   nil,   nil,    68,   nil,   nil,    68,    53,    71,    29,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    25,    27,
+    17,    27,    27,   nil,    59,   nil,    47,   nil,   nil,    51,
+    27,    27,    44,    34,     2,    26,    26,   nil,    61,   nil,
+    24,    49,    24,    24,   nil,    49,    32,    59,   nil,   nil,
+   nil,    24,   nil,    23,   nil,    23,    23,    34,     2,    34,
+     2,    27,    33,   nil,    23,    33,     4,   nil,   nil,   nil,
+    22,   nil,    27,   nil,    25,    26,    25,    25,   nil,   nil,
+    21,   nil,    24,   nil,   nil,    25,   nil,   nil,    27,     4,
+    34,     4,   nil,    24,   nil,    23,    34,     2,    22,   nil,
+   nil,   nil,   nil,   nil,    27,    27,    23,   nil,    21,    24,
+   nil,   nil,     4,    34,   nil,    34,    25,   nil,    26,    26,
+   nil,   nil,    23,   nil,    22,    24,    24,    25,   nil,   nil,
+    27,   nil,   nil,   nil,    21,   nil,    34,   nil,    23,    23,
+   nil,   nil,   nil,    25,   nil,   nil,    22,    22,     4,     4,
+   nil,    24,   nil,    27,   nil,   nil,    21,    21,   nil,    25,
+    25,   nil,    34,     2,    23,   nil,   nil,   nil,   nil,   nil,
+    34,     2,    34,    34,    24,    48,   nil,    48,   nil,    46,
+    22,    46,    22,    22,    28,    25,    28,    23,    28,   nil,
+    21,    22,    21,    21,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,    21,   nil,   nil,   nil,   nil,    22,    48,    25,   nil,
+   nil,    46,   nil,   nil,   nil,   nil,    21,   nil,    28,   nil,
+   nil,   nil,    22,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,    48,    21,    22,   nil,    46,   nil,   nil,    28,   nil,
+   nil,   nil,    28,    21,   nil,   nil,   nil,    48,   nil,    22,
+   nil,    46,   nil,    48,   nil,   nil,   nil,    46,    28,    21,
+   nil,   nil,    22,   nil,    28,    22,    22,   nil,   nil,   nil,
+   nil,   nil,    21,   nil,   nil,    21,    21,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,    22,   nil,   nil,   nil,   nil,   nil,    28,    28,   nil,
+   nil,    21,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,    22,   nil,   nil,   nil,   nil,   nil,
+   nil,    48,    48,   nil,    21,    46,    46,   nil,   nil,   nil,
+   nil,   nil,    28,    28,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,    48,   nil,   nil,
+   nil,    46,   nil,   nil,   nil,   nil,   nil,   nil,    28,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,    48,   nil,   nil,   nil,    46,
+   nil,   nil,   nil,   nil,   nil,   nil,    28,   nil,   nil,    48,
+    48,   nil,   nil,    46,    46,   nil,   nil,   nil,   nil,   nil,
+    28,    28 ]
 
 racc_goto_pointer = [
-   nil,    23,     7,    30,   -18,    39,   nil,   nil,   nil,   nil,
-   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,     1,  -103,
-     0,   221,    87,   -11,   232,   145,     8,   252,    13,   -45,
-  -117,   -40,  -100,     3,     4,   nil,    27,   -15,  -162,   nil,
-   nil,   nil,  -164,   -87,   nil,    14,   -90,   413,   -27,    48,
-   nil,   -21,    -8,  -242,  -204,  -118,  -137,   nil,  -121,   -91,
-  -129,  -166,    22,   -49,    12,    40,    11,    15,  -103,  -102,
-  -148,   -44 ]
+   nil,    19,     1,    12,   -24,    27,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,    -6,   nil,   nil,
+   -73,   167,   157,    30,    17,    51,    10,    -4,   271,    12,
+    -1,   -75,   -23,   -62,     0,    -4,   nil,     8,   -69,  -183,
+   nil,   nil,   nil,  -183,   -33,   nil,   264,   -39,   260,   -23,
+   nil,   -35,   -43,  -121,    17,  -196,   -99,  -118,   nil,  -110,
+   -84,  -119,  -135,    23,   -38,    15,    40,    11,     3,   -83,
+   -82,  -131,   -37 ]
 
 racc_goto_default = [
-   nil,   nil,   nil,   124,    25,    29,    32,     2,     5,     8,
-    10,    12,    14,    18,    21,    24,    28,    31,   nil,    53,
-    76,    78,    79,    81,    83,    85,    86,    89,    30,   nil,
-   nil,   nil,   nil,    59,   nil,    17,   nil,   nil,   126,   197,
-   119,   120,   nil,   nil,   166,    80,    82,   nil,   117,    88,
-   108,   nil,   nil,   185,   nil,   nil,   nil,   236,    68,   nil,
+   nil,   nil,   nil,   150,     4,     7,    10,    12,    14,    16,
+    18,    20,    24,    26,    30,     3,     6,   nil,    52,    55,
+    57,    74,    75,    76,    78,    79,    69,    70,     9,    11,
+   nil,   nil,   nil,   nil,    61,   nil,    29,   nil,   nil,   143,
+   205,   145,   146,   nil,   nil,   119,    63,    80,   nil,   109,
+   104,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   194,    42,
    nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
-   nil,   nil ]
+   nil,   nil,   nil ]
 
 racc_token_table = {
  false => 0,
@@ -741,55 +568,47 @@ racc_token_table = {
  :TRUE => 11,
  :FALSE => 12,
  :EQUALS => 13,
- :APPENDS => 14,
- :LESSEQUAL => 15,
- :NOTEQUAL => 16,
- :DOT => 17,
- :COLON => 18,
- :LLCOLLECT => 19,
- :RRCOLLECT => 20,
- :QMARK => 21,
- :LPAREN => 22,
- :RPAREN => 23,
- :ISEQUAL => 24,
- :GREATEREQUAL => 25,
- :GREATERTHAN => 26,
- :LESSTHAN => 27,
- :IF => 28,
- :ELSE => 29,
- :IMPORT => 30,
- :DEFINE => 31,
- :ELSIF => 32,
- :VARIABLE => 33,
- :CLASS => 34,
- :INHERITS => 35,
- :NODE => 36,
- :BOOLEAN => 37,
- :NAME => 38,
- :SEMIC => 39,
- :CASE => 40,
- :DEFAULT => 41,
- :AT => 42,
- :LCOLLECT => 43,
- :RCOLLECT => 44,
- :CLASSNAME => 45,
- :CLASSREF => 46,
- :NOT => 47,
- :OR => 48,
- :AND => 49,
- :UNDEF => 50,
- :PARROW => 51,
- :PLUS => 52,
- :MINUS => 53,
- :TIMES => 54,
- :DIV => 55,
- :LSHIFT => 56,
- :RSHIFT => 57,
- :UMINUS => 58 }
+ :LESSEQUAL => 14,
+ :NOTEQUAL => 15,
+ :DOT => 16,
+ :COLON => 17,
+ :LLCOLLECT => 18,
+ :RRCOLLECT => 19,
+ :QMARK => 20,
+ :LPAREN => 21,
+ :RPAREN => 22,
+ :ISEQUAL => 23,
+ :GREATEREQUAL => 24,
+ :GREATERTHAN => 25,
+ :LESSTHAN => 26,
+ :IF => 27,
+ :ELSE => 28,
+ :IMPORT => 29,
+ :DEFINE => 30,
+ :ELSIF => 31,
+ :VARIABLE => 32,
+ :CLASS => 33,
+ :INHERITS => 34,
+ :NODE => 35,
+ :BOOLEAN => 36,
+ :NAME => 37,
+ :SEMIC => 38,
+ :CASE => 39,
+ :DEFAULT => 40,
+ :AT => 41,
+ :LCOLLECT => 42,
+ :RCOLLECT => 43,
+ :CLASSNAME => 44,
+ :CLASSREF => 45,
+ :NOT => 46,
+ :OR => 47,
+ :AND => 48,
+ :UNDEF => 49,
+ :PARROW => 50 }
 
 racc_use_result_var = true
 
-racc_nt_base = 59
+racc_nt_base = 51
 
 Racc_arg = [
  racc_action_table,
@@ -822,7 +641,6 @@ Racc_token_to_s_table = [
 'TRUE',
 'FALSE',
 'EQUALS',
-'APPENDS',
 'LESSEQUAL',
 'NOTEQUAL',
 'DOT',
@@ -860,13 +678,6 @@ Racc_token_to_s_table = [
 'AND',
 'UNDEF',
 'PARROW',
-'PLUS',
-'MINUS',
-'TIMES',
-'DIV',
-'LSHIFT',
-'RSHIFT',
-'UMINUS',
 '$start',
 'program',
 'statements',
@@ -884,10 +695,10 @@ Racc_token_to_s_table = [
 'hostclass',
 'nodedef',
 'resourceoverride',
-'append',
 'funcvalues',
+'namestrings',
+'resourcerefs',
 'namestring',
-'resourceref',
 'name',
 'variable',
 'type',
@@ -895,6 +706,7 @@ Racc_token_to_s_table = [
 'funcrvalue',
 'selector',
 'quotedtext',
+'resourceref',
 'classname',
 'resourceinstances',
 'endsemi',
@@ -914,13 +726,13 @@ Racc_token_to_s_table = [
 'resourcename',
 'undef',
 'array',
-'expression',
-'param',
 'rvalue',
+'param',
 'addparam',
 'anyparam',
 'rvalues',
 'comma',
+'iftest',
 'else',
 'caseopts',
 'caseopt',
@@ -946,7 +758,7 @@ Racc_debug_parser = false
 
  # reduce 0 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 42
+module_eval <<'.,.,', 'grammar.ra', 30
   def _reduce_1( val, _values, result )
     if val[0]
         # Make sure we always return an array.
@@ -970,7 +782,7 @@ module_eval <<'.,.,', 'grammar.ra', 42
 
  # reduce 3 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 58
+module_eval <<'.,.,', 'grammar.ra', 46
   def _reduce_4( val, _values, result )
     if val[0] and val[1]
         if val[0].instance_of?(AST::ASTArray)
@@ -1011,10 +823,8 @@ module_eval <<'.,.,', 'grammar.ra', 58
 
  # reduce 16 omitted
 
- # reduce 17 omitted
-
-module_eval <<'.,.,', 'grammar.ra', 81
-  def _reduce_18( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 68
+  def _reduce_17( val, _values, result )
     args = aryfy(val[2])
     result = ast AST::Function,
         :name => val[0],
@@ -1024,19 +834,8 @@ module_eval <<'.,.,', 'grammar.ra', 81
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 88
-  def _reduce_19( val, _values, result )
-    args = aryfy(val[2])
-    result = ast AST::Function,
-        :name => val[0],
-        :arguments => args,
-        :ftype => :statement
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 93
-  def _reduce_20( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 74
+  def _reduce_18( val, _values, result )
     result = ast AST::Function,
         :name => val[0],
         :arguments => AST::ASTArray.new({}),
@@ -1045,8 +844,8 @@ module_eval <<'.,.,', 'grammar.ra', 93
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 100
-  def _reduce_21( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 81
+  def _reduce_19( val, _values, result )
     args = aryfy(val[1])
     result = ast AST::Function,
         :name => val[0],
@@ -1056,12 +855,14 @@ module_eval <<'.,.,', 'grammar.ra', 100
   end
 .,.,
 
- # reduce 22 omitted
+ # reduce 20 omitted
 
- # reduce 23 omitted
+ # reduce 21 omitted
+
+ # reduce 22 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 108
-  def _reduce_24( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 91
+  def _reduce_23( val, _values, result )
     result = aryfy(val[0], val[2])
     result.line = @lexer.line
     result.file = @lexer.file
@@ -1069,18 +870,9 @@ module_eval <<'.,.,', 'grammar.ra', 108
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 117
-  def _reduce_25( val, _values, result )
-    unless val[0].is_a?(AST::ASTArray)
-        val[0] = aryfy(val[0])
-    end
+ # reduce 24 omitted
 
-    val[0].push(val[2])
-
-    result = val[0]
-   result
-  end
-.,.,
+ # reduce 25 omitted
 
  # reduce 26 omitted
 
@@ -1092,18 +884,29 @@ module_eval <<'.,.,', 'grammar.ra', 117
 
  # reduce 30 omitted
 
- # reduce 31 omitted
+module_eval <<'.,.,', 'grammar.ra', 104
+  def _reduce_31( val, _values, result )
+                    result = ast AST::Name, :value => val[0]
+   result
+  end
+.,.,
 
  # reduce 32 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 130
+module_eval <<'.,.,', 'grammar.ra', 115
   def _reduce_33( val, _values, result )
-                    result = ast AST::Name, :value => val[0]
+    unless val[0].is_a?(AST::ASTArray)
+        val[0] = aryfy(val[0])
+    end
+
+    val[0].push(val[2])
+
+    result = val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 151
+module_eval <<'.,.,', 'grammar.ra', 136
   def _reduce_34( val, _values, result )
     array = val[2]
     if array.instance_of?(AST::ResourceInstance)
@@ -1127,7 +930,7 @@ module_eval <<'.,.,', 'grammar.ra', 151
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 154
+module_eval <<'.,.,', 'grammar.ra', 139
   def _reduce_35( val, _values, result )
     # This is a deprecated syntax.
     error "All resource specifications require names"
@@ -1135,7 +938,7 @@ module_eval <<'.,.,', 'grammar.ra', 154
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 157
+module_eval <<'.,.,', 'grammar.ra', 142
   def _reduce_36( val, _values, result )
     # a defaults setting for a type
     result = ast(AST::ResourceDefaults, :type => val[0], :params => val[2])
@@ -1143,19 +946,19 @@ module_eval <<'.,.,', 'grammar.ra', 157
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 162
+module_eval <<'.,.,', 'grammar.ra', 147
   def _reduce_37( val, _values, result )
     result = ast AST::ResourceOverride, :object => val[0], :params => val[2]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 189
+module_eval <<'.,.,', 'grammar.ra', 174
   def _reduce_38( val, _values, result )
     type = val[0]
 
     if (type == :exported and ! Puppet[:storeconfigs]) and ! Puppet[:parseonly]
-        Puppet.warning addcontext("You cannot collect without storeconfigs being set")
+        error "You cannot collect without storeconfigs being set"
     end
 
     if val[1].is_a? AST::ResourceDefaults
@@ -1178,21 +981,21 @@ module_eval <<'.,.,', 'grammar.ra', 189
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 190
+module_eval <<'.,.,', 'grammar.ra', 175
   def _reduce_39( val, _values, result )
  result = :virtual
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 191
+module_eval <<'.,.,', 'grammar.ra', 176
   def _reduce_40( val, _values, result )
  result = :exported
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 214
+module_eval <<'.,.,', 'grammar.ra', 199
   def _reduce_41( val, _values, result )
     if val[0] =~ /^[a-z]/
         Puppet.warning addcontext("Collection names must now be capitalized")
@@ -1208,14 +1011,14 @@ module_eval <<'.,.,', 'grammar.ra', 214
         args[:form] = val[1]
     end
     if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
-        Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
+        error "You cannot collect exported resources without storeconfigs being set"
     end
     result = ast AST::Collection, args
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 224
+module_eval <<'.,.,', 'grammar.ra', 209
   def _reduce_42( val, _values, result )
     if val[1]
         result = val[1]
@@ -1227,7 +1030,7 @@ module_eval <<'.,.,', 'grammar.ra', 224
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 232
+module_eval <<'.,.,', 'grammar.ra', 217
   def _reduce_43( val, _values, result )
     if val[1]
         result = val[1]
@@ -1243,7 +1046,7 @@ module_eval <<'.,.,', 'grammar.ra', 232
 
  # reduce 45 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 240
+module_eval <<'.,.,', 'grammar.ra', 225
   def _reduce_46( val, _values, result )
     result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
    result
@@ -1252,7 +1055,7 @@ module_eval <<'.,.,', 'grammar.ra', 240
 
  # reduce 47 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 246
+module_eval <<'.,.,', 'grammar.ra', 231
   def _reduce_48( val, _values, result )
     result = val[1]
     result.parens = true
@@ -1264,7 +1067,7 @@ module_eval <<'.,.,', 'grammar.ra', 246
 
  # reduce 50 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 254
+module_eval <<'.,.,', 'grammar.ra', 239
   def _reduce_51( val, _values, result )
     result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
     #result = ast AST::CollExpr
@@ -1273,7 +1076,7 @@ module_eval <<'.,.,', 'grammar.ra', 254
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 259
+module_eval <<'.,.,', 'grammar.ra', 244
   def _reduce_52( val, _values, result )
     result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
     #result = ast AST::CollExpr
@@ -1286,7 +1089,7 @@ module_eval <<'.,.,', 'grammar.ra', 259
 
  # reduce 54 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 266
+module_eval <<'.,.,', 'grammar.ra', 251
   def _reduce_55( val, _values, result )
     result = ast AST::ResourceInstance, :children => [val[0],val[2]]
    result
@@ -1295,7 +1098,7 @@ module_eval <<'.,.,', 'grammar.ra', 266
 
  # reduce 56 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 276
+module_eval <<'.,.,', 'grammar.ra', 261
   def _reduce_57( val, _values, result )
     if val[0].instance_of?(AST::ResourceInstance)
         result = ast AST::ASTArray, :children => [val[0],val[2]]
@@ -1311,21 +1114,21 @@ module_eval <<'.,.,', 'grammar.ra', 276
 
  # reduce 59 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 283
+module_eval <<'.,.,', 'grammar.ra', 268
   def _reduce_60( val, _values, result )
     result = ast AST::Undef, :value => :undef
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 287
+module_eval <<'.,.,', 'grammar.ra', 272
   def _reduce_61( val, _values, result )
     result = ast AST::Name, :value => val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 291
+module_eval <<'.,.,', 'grammar.ra', 276
   def _reduce_62( val, _values, result )
     result = ast AST::Type, :value => val[0]
    result
@@ -1344,7 +1147,7 @@ module_eval <<'.,.,', 'grammar.ra', 291
 
  # reduce 68 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 307
+module_eval <<'.,.,', 'grammar.ra', 292
   def _reduce_69( val, _values, result )
     if val[0] =~ /::/
         raise Puppet::ParseError, "Cannot assign to variables in other namespaces"
@@ -1356,30 +1159,22 @@ module_eval <<'.,.,', 'grammar.ra', 307
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 312
+module_eval <<'.,.,', 'grammar.ra', 297
   def _reduce_70( val, _values, result )
-    variable = ast AST::Name, :value => val[0]
-    result = ast AST::VarDef, :name => variable, :value => val[2], :append => true
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 317
-  def _reduce_71( val, _values, result )
     result = ast AST::ASTArray
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 317
-  def _reduce_72( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 297
+  def _reduce_71( val, _values, result )
  result = val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 326
-  def _reduce_73( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 306
+  def _reduce_72( val, _values, result )
     if val[0].instance_of?(AST::ASTArray)
         val[0].push(val[2])
         result = val[0]
@@ -1390,41 +1185,41 @@ module_eval <<'.,.,', 'grammar.ra', 326
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 330
-  def _reduce_74( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 310
+  def _reduce_73( val, _values, result )
     result = ast AST::ResourceParam, :param => val[0], :value => val[2]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 335
-  def _reduce_75( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 315
+  def _reduce_74( val, _values, result )
     result = ast AST::ResourceParam, :param => val[0], :value => val[2],
                                      :add => true
    result
   end
 .,.,
 
- # reduce 76 omitted
+ # reduce 75 omitted
 
- # reduce 77 omitted
+ # reduce 76 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 343
-  def _reduce_78( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 323
+  def _reduce_77( val, _values, result )
     result = ast AST::ASTArray
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 343
-  def _reduce_79( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 323
+  def _reduce_78( val, _values, result )
  result = val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 352
-  def _reduce_80( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 332
+  def _reduce_79( val, _values, result )
     if val[0].instance_of?(AST::ASTArray)
         val[0].push(val[2])
         result = val[0]
@@ -1435,10 +1230,10 @@ module_eval <<'.,.,', 'grammar.ra', 352
   end
 .,.,
 
- # reduce 81 omitted
+ # reduce 80 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 361
-  def _reduce_82( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 341
+  def _reduce_81( val, _values, result )
     if val[0].instance_of?(AST::ASTArray)
         result = val[0].push(val[2])
     else
@@ -1448,6 +1243,8 @@ module_eval <<'.,.,', 'grammar.ra', 361
   end
 .,.,
 
+ # reduce 82 omitted
+
  # reduce 83 omitted
 
  # reduce 84 omitted
@@ -1478,10 +1275,8 @@ module_eval <<'.,.,', 'grammar.ra', 361
 
  # reduce 97 omitted
 
- # reduce 98 omitted
-
-module_eval <<'.,.,', 'grammar.ra', 388
-  def _reduce_99( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 368
+  def _reduce_98( val, _values, result )
     args = aryfy(val[2])
     result = ast AST::Function,
         :name => val[0],
@@ -1491,8 +1286,8 @@ module_eval <<'.,.,', 'grammar.ra', 388
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 393
-  def _reduce_100( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 373
+  def _reduce_99( val, _values, result )
     result = ast AST::Function,
         :name => val[0],
         :arguments => AST::ASTArray.new({}),
@@ -1501,44 +1296,44 @@ module_eval <<'.,.,', 'grammar.ra', 393
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 397
-  def _reduce_101( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 377
+  def _reduce_100( val, _values, result )
     result = ast AST::String, :value => val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 399
-  def _reduce_102( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 379
+  def _reduce_101( val, _values, result )
     result = ast AST::FlatString, :value => val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 403
-  def _reduce_103( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 383
+  def _reduce_102( val, _values, result )
     result = ast AST::Boolean, :value => val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 408
-  def _reduce_104( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 388
+  def _reduce_103( val, _values, result )
     Puppet.warning addcontext("Deprecation notice:  Resource references should now be capitalized")
     result = ast AST::ResourceReference, :type => val[0], :title => val[2]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 410
-  def _reduce_105( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 390
+  def _reduce_104( val, _values, result )
     result = ast AST::ResourceReference, :type => val[0], :title => val[2]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 423
-  def _reduce_106( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 403
+  def _reduce_105( val, _values, result )
     args = {
         :test => val[1],
         :statements => val[3]
@@ -1553,161 +1348,19 @@ module_eval <<'.,.,', 'grammar.ra', 423
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 435
-  def _reduce_107( val, _values, result )
-    args = {
-        :test => val[1],
-        :statements => ast(AST::Nop)
-    }
+ # reduce 106 omitted
 
-    if val[4]
-        args[:else] = val[4]
-    end
-
-    result = ast AST::IfStatement, args
+module_eval <<'.,.,', 'grammar.ra', 408
+  def _reduce_107( val, _values, result )
+    result = ast AST::Else, :statements => val[2]
    result
   end
 .,.,
 
  # reduce 108 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 440
+module_eval <<'.,.,', 'grammar.ra', 420
   def _reduce_109( val, _values, result )
-    result = ast AST::Else, :statements => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 443
-  def _reduce_110( val, _values, result )
-    result = ast AST::Else, :statements => ast(AST::Nop)
-   result
-  end
-.,.,
-
- # reduce 111 omitted
-
-module_eval <<'.,.,', 'grammar.ra', 460
-  def _reduce_112( val, _values, result )
-    result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 463
-  def _reduce_113( val, _values, result )
-    result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 466
-  def _reduce_114( val, _values, result )
-    result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 469
-  def _reduce_115( val, _values, result )
-    result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 472
-  def _reduce_116( val, _values, result )
-    result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 475
-  def _reduce_117( val, _values, result )
-    result = ast AST::ArithmeticOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 478
-  def _reduce_118( val, _values, result )
-    result = ast AST::Minus, :value => val[1]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 481
-  def _reduce_119( val, _values, result )
-    result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 484
-  def _reduce_120( val, _values, result )
-    result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 487
-  def _reduce_121( val, _values, result )
-    result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 490
-  def _reduce_122( val, _values, result )
-    result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 493
-  def _reduce_123( val, _values, result )
-    result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 496
-  def _reduce_124( val, _values, result )
-    result = ast AST::ComparisonOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 499
-  def _reduce_125( val, _values, result )
-    result = ast AST::Not, :value => val[1]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 502
-  def _reduce_126( val, _values, result )
-    result = ast AST::BooleanOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 505
-  def _reduce_127( val, _values, result )
-    result = ast AST::BooleanOperator, :operator => val[1], :lval => val[0], :rval => val[2]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 508
-  def _reduce_128( val, _values, result )
-    result = val[1]
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 516
-  def _reduce_129( val, _values, result )
     options = val[3]
     unless options.instance_of?(AST::ASTArray)
         options = ast AST::ASTArray, :children => [val[3]]
@@ -1717,10 +1370,10 @@ module_eval <<'.,.,', 'grammar.ra', 516
   end
 .,.,
 
- # reduce 130 omitted
+ # reduce 110 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 526
-  def _reduce_131( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 430
+  def _reduce_111( val, _values, result )
     if val[0].instance_of?(AST::ASTArray)
         val[0].push val[1]
         result = val[0]
@@ -1731,15 +1384,15 @@ module_eval <<'.,.,', 'grammar.ra', 526
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 530
-  def _reduce_132( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 434
+  def _reduce_112( val, _values, result )
     result = ast AST::CaseOpt, :value => val[0], :statements => val[3]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 535
-  def _reduce_133( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 439
+  def _reduce_113( val, _values, result )
     result = ast(AST::CaseOpt,
         :value => val[0],
         :statements => ast(AST::ASTArray)
@@ -1748,10 +1401,10 @@ module_eval <<'.,.,', 'grammar.ra', 535
   end
 .,.,
 
- # reduce 134 omitted
+ # reduce 114 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 545
-  def _reduce_135( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 449
+  def _reduce_115( val, _values, result )
     if val[0].instance_of?(AST::ASTArray)
         val[0].push(val[2])
         result = val[0]
@@ -1762,26 +1415,26 @@ module_eval <<'.,.,', 'grammar.ra', 545
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 549
-  def _reduce_136( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 453
+  def _reduce_116( val, _values, result )
     result = ast AST::Selector, :param => val[0], :values => val[2]
    result
   end
 .,.,
 
- # reduce 137 omitted
+ # reduce 117 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 551
-  def _reduce_138( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 455
+  def _reduce_118( val, _values, result )
  result = val[1]
    result
   end
 .,.,
 
- # reduce 139 omitted
+ # reduce 119 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 562
-  def _reduce_140( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 466
+  def _reduce_120( val, _values, result )
     if val[0].instance_of?(AST::ASTArray)
         val[0].push(val[2])
         result = val[0]
@@ -1792,50 +1445,50 @@ module_eval <<'.,.,', 'grammar.ra', 562
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 566
-  def _reduce_141( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 470
+  def _reduce_121( val, _values, result )
     result = ast AST::ResourceParam, :param => val[0], :value => val[2]
    result
   end
 .,.,
 
- # reduce 142 omitted
+ # reduce 122 omitted
 
- # reduce 143 omitted
+ # reduce 123 omitted
 
- # reduce 144 omitted
+ # reduce 124 omitted
 
- # reduce 145 omitted
+ # reduce 125 omitted
 
- # reduce 146 omitted
+ # reduce 126 omitted
 
- # reduce 147 omitted
+ # reduce 127 omitted
 
- # reduce 148 omitted
+ # reduce 128 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 577
-  def _reduce_149( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 481
+  def _reduce_129( val, _values, result )
     result = ast AST::Default, :value => val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 579
-  def _reduce_150( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 483
+  def _reduce_130( val, _values, result )
  result = [val[0].value]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 583
-  def _reduce_151( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 487
+  def _reduce_131( val, _values, result )
     results = val[0] << val[2].value
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 591
-  def _reduce_152( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 495
+  def _reduce_132( val, _values, result )
     val[1].each do |file|
         import(file)
     end
@@ -1845,8 +1498,8 @@ module_eval <<'.,.,', 'grammar.ra', 591
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 601
-  def _reduce_153( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 505
+  def _reduce_133( val, _values, result )
     newdefine classname(val[1]), :arguments => val[2], :code => val[4]
     @lexer.indefine = false
     result = nil
@@ -1856,8 +1509,8 @@ module_eval <<'.,.,', 'grammar.ra', 601
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 605
-  def _reduce_154( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 509
+  def _reduce_134( val, _values, result )
     newdefine classname(val[1]), :arguments => val[2]
     @lexer.indefine = false
     result = nil
@@ -1865,8 +1518,8 @@ module_eval <<'.,.,', 'grammar.ra', 605
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 613
-  def _reduce_155( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 517
+  def _reduce_135( val, _values, result )
     # Our class gets defined in the parent namespace, not our own.
     @lexer.namepop
     newclass classname(val[1]), :code => val[4], :parent => val[2]
@@ -1875,8 +1528,8 @@ module_eval <<'.,.,', 'grammar.ra', 613
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 618
-  def _reduce_156( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 522
+  def _reduce_136( val, _values, result )
     # Our class gets defined in the parent namespace, not our own.
     @lexer.namepop
     newclass classname(val[1]), :parent => val[2]
@@ -1885,32 +1538,32 @@ module_eval <<'.,.,', 'grammar.ra', 618
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 623
-  def _reduce_157( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 527
+  def _reduce_137( val, _values, result )
     newnode val[1], :parent => val[2], :code => val[4]
     result = nil
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 626
-  def _reduce_158( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 530
+  def _reduce_138( val, _values, result )
     newnode val[1], :parent => val[2]
     result = nil
    result
   end
 .,.,
 
- # reduce 159 omitted
+ # reduce 139 omitted
 
- # reduce 160 omitted
+ # reduce 140 omitted
 
- # reduce 161 omitted
+ # reduce 141 omitted
 
- # reduce 162 omitted
+ # reduce 142 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 640
-  def _reduce_163( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 544
+  def _reduce_143( val, _values, result )
     result = val[0]
     result = [result] unless result.is_a?(Array)
     result << val[2]
@@ -1918,49 +1571,49 @@ module_eval <<'.,.,', 'grammar.ra', 640
   end
 .,.,
 
- # reduce 164 omitted
+ # reduce 144 omitted
 
- # reduce 165 omitted
+ # reduce 145 omitted
 
- # reduce 166 omitted
+ # reduce 146 omitted
 
- # reduce 167 omitted
+ # reduce 147 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 649
-  def _reduce_168( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 553
+  def _reduce_148( val, _values, result )
     result = nil
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 653
-  def _reduce_169( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 557
+  def _reduce_149( val, _values, result )
     result = ast AST::ASTArray, :children => []
    result
   end
 .,.,
 
- # reduce 170 omitted
+ # reduce 150 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 658
-  def _reduce_171( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 562
+  def _reduce_151( val, _values, result )
     result = nil
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 662
-  def _reduce_172( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 566
+  def _reduce_152( val, _values, result )
     result = val[1]
     result = [result] unless result[0].is_a?(Array)
    result
   end
 .,.,
 
- # reduce 173 omitted
+ # reduce 153 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 669
-  def _reduce_174( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 573
+  def _reduce_154( val, _values, result )
     result = val[0]
     result = [result] unless result[0].is_a?(Array)
     result << val[2]
@@ -1968,67 +1621,67 @@ module_eval <<'.,.,', 'grammar.ra', 669
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 674
-  def _reduce_175( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 578
+  def _reduce_155( val, _values, result )
     Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
     result = [val[0], val[2]]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 678
-  def _reduce_176( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 582
+  def _reduce_156( val, _values, result )
     Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
     result = [val[0]]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 680
-  def _reduce_177( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 584
+  def _reduce_157( val, _values, result )
     result = [val[0], val[2]]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 682
-  def _reduce_178( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 586
+  def _reduce_158( val, _values, result )
     result = [val[0]]
    result
   end
 .,.,
 
- # reduce 179 omitted
+ # reduce 159 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 687
-  def _reduce_180( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 591
+  def _reduce_160( val, _values, result )
     result = val[1]
    result
   end
 .,.,
 
- # reduce 181 omitted
+ # reduce 161 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 692
-  def _reduce_182( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 596
+  def _reduce_162( val, _values, result )
     result = val[1]
    result
   end
 .,.,
 
- # reduce 183 omitted
+ # reduce 163 omitted
 
- # reduce 184 omitted
+ # reduce 164 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 698
-  def _reduce_185( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 602
+  def _reduce_165( val, _values, result )
     result = ast AST::Variable, :value => val[0]
    result
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 706
-  def _reduce_186( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 610
+  def _reduce_166( val, _values, result )
     if val[1].instance_of?(AST::ASTArray)
         result = val[1]
     else
@@ -2038,32 +1691,21 @@ module_eval <<'.,.,', 'grammar.ra', 706
   end
 .,.,
 
-module_eval <<'.,.,', 'grammar.ra', 713
-  def _reduce_187( val, _values, result )
-    if val[1].instance_of?(AST::ASTArray)
-        result = val[1]
-    else
-        result = ast AST::ASTArray, :children => [val[1]]
-    end
-   result
-  end
-.,.,
-
-module_eval <<'.,.,', 'grammar.ra', 715
-  def _reduce_188( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 612
+  def _reduce_167( val, _values, result )
     result = ast AST::ASTArray
    result
   end
 .,.,
 
- # reduce 189 omitted
+ # reduce 168 omitted
 
- # reduce 190 omitted
+ # reduce 169 omitted
 
- # reduce 191 omitted
+ # reduce 170 omitted
 
-module_eval <<'.,.,', 'grammar.ra', 720
-  def _reduce_192( val, _values, result )
+module_eval <<'.,.,', 'grammar.ra', 617
+  def _reduce_171( val, _values, result )
  result = nil
    result
   end
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index 853d6aa..d70722f 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -95,10 +95,11 @@ class Puppet::Parser::Parser
                 raise Puppet::Error, "Could not find file %s" % file
             end
         end
-        if check_and_add_to_watched_files(file)
-            @lexer.file = file
-        else
+        if @files.detect { |f| f.file == file }
             raise Puppet::AlreadyImportedError.new("Import loop detected")
+        else
+            @files << Puppet::Util::LoadedFile.new(file)
+            @lexer.file = file
         end
     end
 
@@ -215,7 +216,7 @@ class Puppet::Parser::Parser
     # Initialize or reset all of our variables.
     def initvars
         @lexer = Puppet::Parser::Lexer.new()
-        @files = {}
+        @files = []
         @loaded = []
     end
 
@@ -434,8 +435,8 @@ class Puppet::Parser::Parser
 
     # See if any of the files have changed.
     def reparse?
-        if file = @files.detect { |name, file| file.changed?  }
-            return file[1].stamp
+        if file = @files.detect { |file| file.changed?  }
+            return file.stamp
         else
             return false
         end
@@ -448,18 +449,12 @@ class Puppet::Parser::Parser
     # Add a new file to be checked when we're checking to see if we should be
     # reparsed.  This is basically only used by the TemplateWrapper to let the
     # parser know about templates that should be parsed.
-    def watch_file(filename)
-            check_and_add_to_watched_files(filename)
-    end
-
-    private
-
-    def check_and_add_to_watched_files(filename)
-        unless @files.include?(filename)    
-            @files[filename] = Puppet::Util::LoadedFile.new(filename)
-            return true
-        else
-            return false
+    def watch_file(*files)
+        files.each do |file|
+            unless file.is_a? Puppet::Util::LoadedFile
+                file = Puppet::Util::LoadedFile.new(file)
+            end
+            @files << file
         end
     end
 end
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index 747338b..d214a60 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -369,7 +369,7 @@ class Puppet::Parser::Resource
             next unless val = scope.lookupvar(name.to_s, false) and val != :undefined
 
             # The default case: just set the value
-            set_parameter(name, val) and next unless @params[name]
+            return set_parameter(name, val) unless @params[name]
 
             # For relationship params, though, join the values (a la #446).
             @params[name].value = [@params[name].value, val].flatten
diff --git a/lib/puppet/parser/resource/param.rb b/lib/puppet/parser/resource/param.rb
index c8dd78a..9dd3f26 100644
--- a/lib/puppet/parser/resource/param.rb
+++ b/lib/puppet/parser/resource/param.rb
@@ -66,14 +66,6 @@ class Puppet::Parser::Resource::Param
     def to_s
         "%s => %s" % [self.name, self.value]
     end
-
-    def compare(v,db_value)
-      if (v.is_a?(Puppet::Parser::Resource::Reference))
-        return v.to_s == db_value.to_s
-      else
-        return v == db_value
-      end
-    end
     
     def values_to_remove(db_values)
         values = munge_for_rails(value)
@@ -81,7 +73,7 @@ class Puppet::Parser::Resource::Param
         db_values.collect do |db|
             db unless (db.line == line_number && 
                        values.find { |v| 
-                         compare(v,db.value)
+                         v == db.value 
                        } )
         end.compact
     end
@@ -90,7 +82,7 @@ class Puppet::Parser::Resource::Param
         values = munge_for_rails(value)
         line_number = line_to_i()
         values.collect do |v|
-            v unless db_values.find { |db| (compare(v,db.value) && 
+            v unless db_values.find { |db| (v == db.value && 
                                          line_number == db.line) }
         end.compact
     end
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 4acdf41..a6e43e7 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -43,29 +43,6 @@ class Puppet::Parser::Scope
         end
     end
 
-    # Is the value a number?, return the correct object or nil if not a number
-    def self.number?(value)
-        unless value.is_a?(Fixnum) or value.is_a?(Bignum) or value.is_a?(Float) or value.is_a?(String)
-            return nil
-        end
-        
-        if value.is_a?(String)
-            if value =~ /^-?\d+(:?\.\d+|(:?\.\d+)?e\d+)$/
-                return value.to_f
-            elsif value =~ /^0x\d+/i
-                return value.to_i(16)
-            elsif value =~ /^0\d+/i
-                return value.to_i(8)
-            elsif value =~ /^-?\d+/
-                return value.to_i
-            else
-                return nil
-            end
-        end
-        # it is one of Fixnum,Bignum or Float
-        return value
-    end
-
     # Add to our list of namespaces.
     def add_namespace(ns)
         return false if @namespaces.include?(ns)
@@ -206,25 +183,6 @@ class Puppet::Parser::Scope
         end
     end
 
-    # Return a hash containing our variables and their values, optionally (and
-    # by default) including the values defined in our parent.  Local values
-    # shadow parent values.
-    def to_hash(recursive = true)
-        if recursive and parent then
-            target = parent.to_hash(recursive)
-        end
-        target ||= Hash.new
-        @symtable.keys.each { |name| 
-            value = @symtable[name]
-            if value == :undef then
-                target.delete(name)
-            else
-                target[name] = value 
-            end
-        }
-        return target
-    end
-
     def namespaces
         @namespaces.dup
     end
@@ -283,15 +241,11 @@ class Puppet::Parser::Scope
     # Set a variable in the current scope.  This will override settings
     # in scopes above, but will not allow variables in the current scope
     # to be reassigned.
-    def setvar(name,value, file = nil, line = nil, append = false)
-        #Puppet.debug "Setting %s to '%s' at level %s mode append %s" %
-        #    [name.inspect,value,self.level, append]
+    def setvar(name,value, file = nil, line = nil)
+        #Puppet.debug "Setting %s to '%s' at level %s" %
+        #    [name.inspect,value,self.level]
         if @symtable.include?(name)
-            unless append
-                error = Puppet::ParseError.new("Cannot reassign variable %s" % name)
-            else
-                error = Puppet::ParseError.new("Cannot append, variable %s is defined in this scope" % name)
-            end
+            error = Puppet::ParseError.new("Cannot reassign variable %s" % name)
             if file
                 error.file = file
             end
@@ -300,19 +254,7 @@ class Puppet::Parser::Scope
             end
             raise error
         end
-        
-        unless append
-            @symtable[name] = value
-        else # append case
-            # lookup the value in the scope if it exists and insert the var
-            @symtable[name] = lookupvar(name)
-            # concatenate if string, append if array, nothing for other types
-            if value.is_a?(Array)
-                @symtable[name] += value
-            else
-                @symtable[name] << value
-            end
-        end
+        @symtable[name] = value
     end
 
     # Return an interpolated string.
diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb
index 036f660..7a8f741 100644
--- a/lib/puppet/parser/templatewrapper.rb
+++ b/lib/puppet/parser/templatewrapper.rb
@@ -5,96 +5,41 @@ class Puppet::Parser::TemplateWrapper
     include Puppet::Util
     Puppet::Util.logmethods(self)
 
-    def initialize(scope, filename)
-        @__scope__ = scope
-        @__file__ = Puppet::Module::find_template(filename, scope.compiler.environment)
+    def initialize(scope, file)
+        @scope = scope
+        @file = Puppet::Module::find_template(file, @scope.compiler.environment)
 
-        unless FileTest.exists?(file)
+        unless FileTest.exists?(@file)
             raise Puppet::ParseError,
                 "Could not find template %s" % file
         end
 
         # We'll only ever not have a parser in testing, but, eh.
-        if scope.parser
-            scope.parser.watch_file(file)
+        if @scope.parser
+            @scope.parser.watch_file(@file)
         end
     end
 
-    def scope
-        @__scope__
-    end
-
-    def file
-        @__file__
-    end
-
-    # Should return true if a variable is defined, false if it is not
-    def has_variable?(name)
-        if scope.lookupvar(name.to_s, false) != :undefined
-            true
-        else
-            false
-        end
-    end
-
-    # Allow templates to access the defined classes
-    def classes
-        return scope.catalog.classes
-    end
-
-    # Allow templates to access the tags defined in the current scope
-    def tags
-        return scope.tags
-    end
-
-    # Allow templates to access the all the defined tags
-    def all_tags
-        return scope.catalog.tags
-    end
-
-    # Ruby treats variables like methods, so we used to expose variables
-    # within scope to the ERB code via method_missing.  As per RedMine #1427,
-    # though, this means that conflicts between methods in our inheritance
-    # tree (Kernel#fork) and variable names (fork => "yes/no") could arise.
-    #
-    # Worse, /new/ conflicts could pop up when a new kernel or object method
-    # was added to Ruby, causing templates to suddenly fail mysteriously when
-    # Ruby was upgraded.
-    #
-    # To ensure that legacy templates using unqualified names work we retain
-    # the missing_method definition here until we declare the syntax finally
-    # dead.
+    # Ruby treats variables like methods, so we can cheat here and
+    # trap missing vars like they were missing methods.
     def method_missing(name, *args)
         # We have to tell lookupvar to return :undefined to us when
         # appropriate; otherwise it converts to "".
-        value = scope.lookupvar(name.to_s, false)
+        value = @scope.lookupvar(name.to_s, false)
         if value != :undefined
             return value
         else
             # Just throw an error immediately, instead of searching for
             # other missingmethod things or whatever.
-            raise Puppet::ParseError, "Could not find value for '%s'" % name
+            raise Puppet::ParseError,
+                "Could not find value for '%s'" % name
         end
     end
 
     def result
-        # Expose all the variables in our scope as instance variables of the
-        # current object, making it possible to access them without conflict
-        # to the regular methods.
-        benchmark(:debug, "Bound template variables for #{file}") do
-            scope.to_hash.each { |name, value| 
-                if name.kind_of?(String)
-                    realname = name.gsub(/[^\w]/, "_")
-                else
-                    realname = name
-                end
-                instance_variable_set("@#{realname}", value)
-            }
-        end
-
         result = nil
-        benchmark(:debug, "Interpolated template #{file}") do
-            template = ERB.new(File.read(file), 0, "-")
+        benchmark(:debug, "Interpolated template #{@file}") do
+            template = ERB.new(File.read(@file), 0, "-")
             result = template.result(binding)
         end
 
@@ -102,7 +47,7 @@ class Puppet::Parser::TemplateWrapper
     end
 
     def to_s
-        "template[%s]" % file
+        "template[%s]" % @file
     end
 end
 
diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb
index 55ad7d2..3bcc2ce 100644
--- a/lib/puppet/pgraph.rb
+++ b/lib/puppet/pgraph.rb
@@ -58,7 +58,7 @@ class Puppet::PGraph < Puppet::SimpleGraph
             # to, which is the same thing as saying all edges directly below
             # This vertex in the graph.
             adjacent(source, :direction => :out, :type => :edges).find_all do |edge|
-                edge.match?(event.name)
+                edge.match?(event.event)
             end
         end.compact.flatten
     end
diff --git a/lib/puppet/property.rb b/lib/puppet/property.rb
index 50a1b71..fcaa19d 100644
--- a/lib/puppet/property.rb
+++ b/lib/puppet/property.rb
@@ -2,6 +2,7 @@
 # blocks for actually doing work on the system.
 
 require 'puppet'
+require 'puppet/propertychange'
 require 'puppet/parameter'
 
 module Puppet
@@ -441,13 +442,7 @@ class Property < Puppet::Parameter
         return "%s(%s)" % [@resource.name,self.name]
     end
 
-    # Just return any should value we might have.
-    def value
-        self.should
-    end
-
-    # Match the Parameter interface, but we really just use 'should' internally.
-    # Note that the should= method does all of the validation and such.
+    # Provide a common hook for setting @should, just like params.
     def value=(value)
         self.should = value
     end
diff --git a/lib/puppet/property/keyvalue.rb b/lib/puppet/property/keyvalue.rb
deleted file mode 100644
index 6c0800c..0000000
--- a/lib/puppet/property/keyvalue.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-#This subclass of property manages string key value pairs.
-
-#In order to use this property:
-# - the @should value must be an array of keyvalue pairs separated by the 'separator'
-# - the retrieve method should return a hash with the keys as symbols
-# IMPORTANT NOTE: In order for this property to work there must also be a 'membership' parameter
-# The class that inherits from property should override that method with the symbol for the membership
-
-require 'puppet/property'
-
-module Puppet
-    class Property
-        class KeyValue < Property
-
-            def hash_to_key_value_s(hash)
-                hash.select { |k,v| true }.map { |pair| pair.join(separator) }.join(delimiter)
-            end
-
-            def should_to_s(should_value)
-                hash_to_key_value_s(should_value)
-            end
-
-            def is_to_s(current_value)
-                hash_to_key_value_s(current_value)
-            end
-
-            def membership
-                :key_value_membership
-            end
-
-            def inclusive?
-                @resource[membership] == :inclusive
-            end
-
-            def hashify(key_value_array)
-                #turns string array into a hash
-                key_value_array.inject({}) do |hash, key_value|
-                    tmp = key_value.split(separator)
-                    hash[tmp[0].intern] = tmp[1]
-                    hash
-                end
-            end
-
-            def process_current_hash(current)
-                return {} if current == :absent
-
-                #inclusive means we are managing everything so if it isn't in should, its gone
-                if inclusive?
-                    current.each_key { |key| current[key] = nil }
-                end
-                current
-            end
-
-            def should
-                unless defined? @should and @should
-                    return nil
-                end
-
-                members = hashify(@should)
-                current = process_current_hash(retrieve)
-
-                #shared keys will get overwritten by members
-                current.merge(members)
-            end
-
-            def separator
-                "="
-            end
-
-            def delimiter
-                ";"
-            end
-
-            def retrieve
-                #ok, some 'convention' if the keyvalue property is named properties, provider should implement a properties method
-                if key_hash = provider.send(name) and key_hash != :absent
-                    return key_hash
-                else
-                    return :absent
-                end
-            end
-
-            def insync?(is)
-                unless defined? @should and @should
-                    return true
-                end
-
-                unless is
-                    return true
-                end
-
-                return (is == self.should)
-            end
-        end
-    end
-end
diff --git a/lib/puppet/property/list.rb b/lib/puppet/property/list.rb
deleted file mode 100644
index 4e7f6ec..0000000
--- a/lib/puppet/property/list.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-require 'puppet/property'
-
-module Puppet
-    class Property
-        class List < Property
-
-            def should_to_s(should_value)
-                #just return the should value
-                should_value
-            end
-
-            def is_to_s(currentvalue)
-                currentvalue.join(delimiter)
-            end
-
-            def membership
-                :membership
-            end
-
-            def add_should_with_current(should, current)
-                if current.is_a?(Array)
-                    should += current
-                end
-                should.uniq
-            end
-
-            def inclusive?
-                @resource[membership] == :inclusive
-            end
-
-            def should
-                unless defined? @should and @should
-                    return nil
-                end
-
-                members = @should
-                #inclusive means we are managing everything so if it isn't in should, its gone
-                if ! inclusive?
-                    members = add_should_with_current(members, retrieve)
-                end
-
-                members.sort.join(delimiter)
-            end
-
-            def delimiter
-                ","
-            end
-
-            def retrieve
-                #ok, some 'convention' if the list property is named groups, provider should implement a groups method
-                if tmp = provider.send(name) and tmp != :absent
-                    return tmp.split(delimiter)
-                else
-                    return :absent
-                end
-            end
-
-            def prepare_is_for_comparison(is)
-                if is.is_a? Array
-                    is = is.sort.join(delimiter)
-                end
-                is
-            end
-
-            def insync?(is)
-                unless defined? @should and @should
-                    return true
-                end
-
-                unless is
-                    return true
-                end
-
-                return (prepare_is_for_comparison(is) == self.should)
-            end
-        end
-    end
-end
diff --git a/lib/puppet/propertychange.rb b/lib/puppet/propertychange.rb
new file mode 100644
index 0000000..35bbede
--- /dev/null
+++ b/lib/puppet/propertychange.rb
@@ -0,0 +1,141 @@
+# the class responsible for actually doing any work
+
+# enables no-op and logging/rollback
+
+module Puppet
+    # Handle all of the work around performing an actual change,
+    # including calling 'sync' on the properties and producing events.
+	class PropertyChange
+        attr_accessor :is, :should, :type, :path, :property, :transaction, :changed, :proxy
+        
+        # The log file generated when this object was changed.
+        attr_reader :report
+        
+        # Switch the goals of the property, thus running the change in reverse.
+        def backward
+            @property.should = @is
+            @is = @property.retrieve
+
+            unless defined? @transaction
+                raise Puppet::Error,
+                    "PropertyChange '%s' tried to be executed outside of transaction" %
+                    self
+            end
+            unless @property.insync?(@is)
+                @property.info "Backing %s" % self
+                return self.go
+            else
+                @property.debug "rollback is already in sync: %s vs. %s" %
+                    [@is, @property.should.inspect]
+                return nil
+            end
+        end
+        
+        def changed?
+            self.changed
+        end
+
+        # Create our event object.
+        def event(name)
+            # default to a simple event type
+            unless name.is_a?(Symbol)
+                @property.warning("Property '%s' returned invalid event '%s'; resetting to default" %
+                    [@property.class, name])
+
+                event = @property.resource.class.name.id2name + "_changed"
+            end
+            
+            Puppet::Event.new(
+                :event => name,
+                :transaction => @transaction,
+                :source => self.source
+            )
+        end
+
+        def initialize(property, currentvalue)
+            unless property.is_a?(Puppet::Property)
+                raise Puppet::DevError, "Got a %s instead of a property" %
+                    property.class
+            end
+            @property = property
+            @path = [property.path,"change"].flatten
+            @is = currentvalue
+
+            @should = property.should
+
+            @changed = false
+        end
+
+        # Perform the actual change.  This method can go either forward or
+        # backward, and produces an event.
+        def go
+            if skip?
+                if self.noop
+                    return [event(:noop)]
+                else
+                    return nil
+                end
+            end
+
+            # The transaction catches any exceptions here.
+            events = @property.sync
+            if events.nil?
+                return nil
+            end
+
+            if events.is_a?(Array)
+                if events.empty?
+                    return nil
+                end
+            else
+                events = [events]
+            end
+            
+            return events.collect { |name|
+                @report = @property.log(@property.change_to_s(@is, @should))
+                event(name)
+            }
+        end
+
+        def forward
+            #@property.debug "moving change forward"
+
+            unless defined? @transaction
+                raise Puppet::Error,
+                    "PropertyChange '%s' tried to be executed outside of transaction" %
+                    self
+            end
+
+            return self.go
+        end
+        
+        def noop
+            return @property.noop
+        end
+        
+        def skip?
+            if @property.insync?(@is)
+                @property.info "Already in sync"
+                return true
+            end
+
+            if @property.noop
+                @property.log "is %s, should be %s (noop)" %
+                    [property.is_to_s(@is), property.should_to_s(@should)]
+                #@property.debug "%s is noop" % @property
+                return true
+            end
+            return false
+        end
+        
+        def source
+            self.proxy || @property.resource
+        end
+
+        def to_s
+            return "change %s.%s(%s)" %
+                [@transaction.object_id, self.object_id, @property.change_to_s(@is, @should)]
+            #return "change %s.%s" % [@transaction.object_id, self.object_id]
+        end
+	end
+end
diff --git a/lib/puppet/provider.rb b/lib/puppet/provider.rb
index c02e150..e73bb0c 100644
--- a/lib/puppet/provider.rb
+++ b/lib/puppet/provider.rb
@@ -5,10 +5,6 @@ class Puppet::Provider
     include Puppet::Util::Warnings
     extend Puppet::Util::Warnings
 
-    require 'puppet/provider/confiner'
-
-    extend Puppet::Provider::Confiner
-
     Puppet::Util.logmethods(self, true)
 
     class << self
@@ -44,13 +40,27 @@ class Puppet::Provider
                 [name, self.name]
         end
 
-        return binary(command)
+        if command == :missing
+            return nil
+        end
+
+        command
     end
 
     # Define commands that are not optional.
     def self.commands(hash)
         optional_commands(hash) do |name, path|
-            confine :exists => path, :for_binary => true
+            confine :exists => path
+        end
+    end
+
+    def self.confine(hash)
+        hash.each do |p,v|
+            if v.is_a? Array
+                @confines[p] += v
+            else
+                @confines[p] << v
+            end
         end
     end
 
@@ -98,6 +108,10 @@ class Puppet::Provider
     def self.initvars
         @defaults = {}
         @commands = {}
+        @origcommands = {}
+        @confines = Hash.new do |hash, key|
+            hash[key] = []
+        end
     end
 
     # The method for returning a list of provider instances.  Note that it returns providers, preferably with values already
@@ -166,7 +180,16 @@ class Puppet::Provider
     def self.optional_commands(hash)
         hash.each do |name, path|
             name = symbolize(name)
-            @commands[name] = path
+            @origcommands[name] = path
+
+            # Try to find the full path (or verify already-full paths); otherwise
+            # store that the command is missing so we know it's defined but absent.
+            if tmp = binary(path)
+                path = tmp
+                @commands[name] = path
+            else
+                @commands[name] = :missing
+            end
 
             if block_given?
                 yield(name, path)
@@ -185,6 +208,69 @@ class Puppet::Provider
         @source
     end
 
+    # Check whether this implementation is suitable for our platform.
+    def self.suitable?(short = true)
+        # A single false result is sufficient to turn the whole thing down.
+        # We don't return 'true' until the very end, though, so that every
+        # confine is tested.
+        missing = {}
+        @confines.each do |check, values|
+            case check
+            when :exists:
+                values.each do |value|
+                    unless value and FileTest.exists? value
+                        debug "Not suitable: missing %s" % value
+                        return false if short
+                        missing[:exists] ||= []
+                        missing[:exists] << value
+                    end
+                end
+            when :true:
+                values.each do |v|
+                    debug "Not suitable: false value"
+                    unless v
+                        return false if short
+                        missing[:true] ||= 0
+                        missing[:true] += 1
+                    end
+                end
+            when :false:
+                values.each do |v|
+                    debug "Not suitable: true value"
+                    if v and short
+                        return false if short
+                        missing[:false] ||= 0
+                        missing[:false] += 1
+                    end
+                end
+            else # Just delegate everything else to facter
+                if result = Facter.value(check)
+                    result = result.to_s.downcase.intern
+
+                    found = values.find do |v|
+                        result == v.to_s.downcase.intern
+                    end
+                    unless found
+                        debug "Not suitable: %s not in %s" % [check, values]
+                        return false if short
+                        missing[:facter] ||= {}
+                        missing[:facter][check] = values
+                    end
+                else
+                    return false if short
+                    missing[:facter] ||= {}
+                    missing[:facter][check] = values
+                end
+            end
+        end
+
+        if short
+            return true
+        else
+            return missing
+        end
+    end
+
     # Does this provider support the specified parameter?
     def self.supports_parameter?(param)
         if param.is_a?(Class)
@@ -223,8 +309,8 @@ class Puppet::Provider
     end
 
     dochook(:commands) do
-        if @commands.length > 0
-            return "  Required binaries: " + @commands.collect do |n, c|
+        if @origcommands.length > 0
+            return "  Required binaries: " + @origcommands.collect do |n, c|
                 "``#{c}``"
             end.join(", ") + "."
         end
diff --git a/lib/puppet/provider/confine.rb b/lib/puppet/provider/confine.rb
deleted file mode 100644
index 70148fc..0000000
--- a/lib/puppet/provider/confine.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# The class that handles testing whether our providers
-# actually work or not.
-require 'puppet/util'
-
-class Puppet::Provider::Confine
-    include Puppet::Util
-
-    @tests = {}
-
-    class << self
-        attr_accessor :name
-    end
-
-    def self.inherited(klass)
-        name = klass.to_s.split("::").pop.downcase.to_sym
-        raise "Test %s is already defined" % name if @tests.include?(name)
-
-        klass.name = name
-
-        @tests[name] = klass
-    end
-
-    def self.test(name)
-        unless @tests[name]
-            begin
-                require "puppet/provider/confine/%s" % name
-            rescue LoadError => detail
-                unless detail.to_s =~ /No such file/i
-                    warn "Could not load confine test '%s': %s" % [name, detail]
-                end
-                # Could not find file
-            end
-        end
-        return @tests[name]
-    end
-
-    attr_reader :values
-
-    # Mark that this confine is used for testing binary existence.
-    attr_accessor :for_binary
-    def for_binary?
-        for_binary
-    end
-
-    def initialize(values)
-        values = [values] unless values.is_a?(Array)
-        @values = values
-    end
-
-    # Provide a hook for the message when there's a failure.
-    def message(value)
-        ""
-    end
-
-    # Collect the results of all of them.
-    def result
-        values.collect { |value| pass?(value) }
-    end
-
-    # Test whether our confine matches.
-    def valid?
-        values.each do |value|
-            unless pass?(value)
-                Puppet.debug message(value)
-                return false
-            end
-        end
-
-        return true
-    ensure
-        reset
-    end
-
-    # Provide a hook for subclasses.
-    def reset
-    end
-end
diff --git a/lib/puppet/provider/confine/exists.rb b/lib/puppet/provider/confine/exists.rb
deleted file mode 100644
index 1d1ed8c..0000000
--- a/lib/puppet/provider/confine/exists.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'puppet/provider/confine'
-
-class Puppet::Provider::Confine::Exists < Puppet::Provider::Confine
-    def self.summarize(confines)
-        confines.inject([]) { |total, confine| total + confine.summary }
-    end
-
-    def pass?(value)
-        if for_binary?
-            return false unless value = binary(value)
-        end
-        value and FileTest.exist?(value)
-    end
-
-    def message(value)
-        "file %s does not exist" % value
-    end
-
-    def summary
-        result.zip(values).inject([]) { |array, args| val, f = args; array << f unless val; array }
-    end
-end
diff --git a/lib/puppet/provider/confine/false.rb b/lib/puppet/provider/confine/false.rb
deleted file mode 100644
index b5b2b51..0000000
--- a/lib/puppet/provider/confine/false.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require 'puppet/provider/confine'
-
-class Puppet::Provider::Confine::False < Puppet::Provider::Confine
-    def self.summarize(confines)
-        confines.inject(0) { |count, confine| count + confine.summary }
-    end
-
-    def pass?(value)
-        ! value
-    end
-
-    def message(value)
-        "true value when expecting false"
-    end
-
-    def summary
-        result.find_all { |v| v == false }.length
-    end
-end
diff --git a/lib/puppet/provider/confine/feature.rb b/lib/puppet/provider/confine/feature.rb
deleted file mode 100644
index 1d92b00..0000000
--- a/lib/puppet/provider/confine/feature.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'puppet/provider/confine'
-
-class Puppet::Provider::Confine::Feature < Puppet::Provider::Confine
-    def self.summarize(confines)
-        confines.collect { |c| c.values }.flatten.uniq.find_all { |value| ! confines[0].pass?(value) }
-    end
-
-    # Is the named feature available?
-    def pass?(value)
-        Puppet.features.send(value.to_s + "?")
-    end
-
-    def message(value)
-        "feature %s is missing" % value
-    end
-end
-
diff --git a/lib/puppet/provider/confine/true.rb b/lib/puppet/provider/confine/true.rb
deleted file mode 100644
index 86b3b14..0000000
--- a/lib/puppet/provider/confine/true.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'puppet/provider/confine'
-
-class Puppet::Provider::Confine::True < Puppet::Provider::Confine
-    def self.summarize(confines)
-        confines.inject(0) { |count, confine| count + confine.summary }
-    end
-
-    def pass?(value)
-        # Double negate, so we only get true or false.
-        ! ! value
-    end
-
-    def message(value)
-        "false value when expecting true"
-    end
-
-    def summary
-        result.find_all { |v| v == true }.length
-    end
-end
diff --git a/lib/puppet/provider/confine/variable.rb b/lib/puppet/provider/confine/variable.rb
deleted file mode 100644
index 0ef90d6..0000000
--- a/lib/puppet/provider/confine/variable.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require 'puppet/provider/confine'
-
-# Require a specific value for a variable, either a Puppet setting
-# or a Facter value.  This class is a bit weird because the name
-# is set explicitly by the ConfineCollection class -- from this class,
-# it's not obvious how the name would ever get set.
-class Puppet::Provider::Confine::Variable < Puppet::Provider::Confine
-    # Provide a hash summary of failing confines -- the key of the hash
-    # is the name of the confine, and the value is the missing yet required values.
-    # Only returns failed values, not all required values.
-    def self.summarize(confines)
-        result = Hash.new { |hash, key| hash[key] = [] }
-        confines.inject(result) { |total, confine| total[confine.name] += confine.values unless confine.valid?; total }
-    end
-
-    # This is set by ConfineCollection.
-    attr_accessor :name
-
-    # Retrieve the value from facter
-    def facter_value
-        unless defined?(@facter_value) and @facter_value
-            @facter_value = ::Facter.value(name).to_s.downcase
-        end
-        @facter_value
-    end
-
-    def message(value)
-        "facter value '%s' for '%s' not in required list '%s'" % [value, self.name, values.join(",")]
-    end
-
-    # Compare the passed-in value to the retrieved value.
-    def pass?(value)
-        test_value.downcase.to_s == value.to_s.downcase
-    end
-
-    def reset
-        # Reset the cache.  We want to cache it during a given
-        # run, but across runs.
-        @facter_value = nil
-    end
-
-    private
-
-    def setting?
-        Puppet.settings.valid?(name)
-    end
-
-    def test_value
-        setting? ? Puppet.settings[name] : facter_value 
-    end
-end
diff --git a/lib/puppet/provider/confine_collection.rb b/lib/puppet/provider/confine_collection.rb
deleted file mode 100644
index 35f461a..0000000
--- a/lib/puppet/provider/confine_collection.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# Manage a collection of confines, returning a boolean or
-# helpful information.
-require 'puppet/provider/confine'
-
-class Puppet::Provider::ConfineCollection
-    def confine(hash)
-        if hash.include?(:for_binary)
-            for_binary = true
-            hash.delete(:for_binary)
-        else
-            for_binary = false
-        end
-        hash.each do |test, values|
-            if klass = Puppet::Provider::Confine.test(test)
-                @confines << klass.new(values)
-                @confines[-1].for_binary = true if for_binary
-            else
-                confine = Puppet::Provider::Confine.test(:variable).new(values)
-                confine.name = test
-                @confines << confine
-            end
-        end
-    end
-
-    def initialize
-        @confines = []
-    end
-
-    # Return a hash of the whole confine set, used for the Provider
-    # reference.
-    def summary
-        confines = Hash.new { |hash, key| hash[key] = [] }
-        @confines.each { |confine| confines[confine.class] << confine }
-        result = {}
-        confines.each do |klass, list|
-            value = klass.summarize(list)
-            next if (value.respond_to?(:length) and value.length == 0) or (value == 0)
-            result[klass.name] = value
-
-        end
-        result
-    end
-
-    def valid?
-        ! @confines.detect { |c| ! c.valid? }
-    end
-end
diff --git a/lib/puppet/provider/confiner.rb b/lib/puppet/provider/confiner.rb
deleted file mode 100644
index 4605523..0000000
--- a/lib/puppet/provider/confiner.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'puppet/provider/confine_collection'
-
-module Puppet::Provider::Confiner
-    def confine(hash)
-        confine_collection.confine(hash)
-    end
-
-    def confine_collection
-        unless defined?(@confine_collection)
-            @confine_collection = Puppet::Provider::ConfineCollection.new
-        end
-        @confine_collection
-    end
-
-    # Check whether this implementation is suitable for our platform.
-    def suitable?(short = true)
-        return confine_collection.valid? if short
-        return confine_collection.summary
-    end
-end
diff --git a/lib/puppet/provider/cron/crontab.rb b/lib/puppet/provider/cron/crontab.rb
index 1cfa0f5..7ddcc05 100755
--- a/lib/puppet/provider/cron/crontab.rb
+++ b/lib/puppet/provider/cron/crontab.rb
@@ -30,7 +30,7 @@ Puppet::Type.type(:cron).provide(:crontab,
         }
 
     crontab = record_line :crontab, :fields => %w{minute hour monthday month weekday command},
-        :match => %r{^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)$},
+        :match => %r{^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)$},
         :optional => %w{minute hour weekday month monthday}, :absent => "*"
 
     class << crontab
@@ -69,11 +69,7 @@ Puppet::Type.type(:cron).provide(:crontab,
                 end
             end
 
-            if record[:special]
-                str += "@%s %s" % [record[:special], record[:command]]
-            else
-                str += join(record)
-            end
+            str += join(record)
             str
         end
     end
diff --git a/lib/puppet/provider/group/groupadd.rb b/lib/puppet/provider/group/groupadd.rb
index 371beee..4df5bf4 100644
--- a/lib/puppet/provider/group/groupadd.rb
+++ b/lib/puppet/provider/group/groupadd.rb
@@ -17,7 +17,7 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
                 cmd << flag(:gid) << gid
             end
         end
-        if @resource.allowdupe?
+        if @resource[:allowdupe] == :true
             cmd << "-o"
         end
         cmd << @resource[:name]
diff --git a/lib/puppet/provider/group/ldap.rb b/lib/puppet/provider/group/ldap.rb
deleted file mode 100644
index 37a7e73..0000000
--- a/lib/puppet/provider/group/ldap.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require 'puppet/provider/ldap'
-
-Puppet::Type.type(:group).provide :ldap, :parent => Puppet::Provider::Ldap do
-    desc "Group management via ``ldap``.  This provider requires that you
-        have valid values for all of the ldap-related settings,
-        including ``ldapbase``.  You will also almost definitely need settings
-        for ``ldapuser`` and ``ldappassword``, so that your clients can write
-        to ldap.
-        
-        Note that this provider will automatically generate a GID for you if
-        you do not specify one, but it is a potentially expensive operation,
-        as it iterates across all existing groups to pick the appropriate next
-        one."
-
-    confine :true => Puppet.features.ldap?, :false => (Puppet[:ldapuser] == "")
-
-    # We're mapping 'members' here because we want to make it
-    # easy for the ldap user provider to manage groups.  This
-    # way it can just use the 'update' method in the group manager,
-    # whereas otherwise it would need to replicate that code.
-    manages(:posixGroup).at("ou=Groups").and.maps :name => :cn, :gid => :gidNumber, :members => :memberUid
-
-    # Find the next gid after the current largest gid.
-    provider = self
-    manager.generates(:gidNumber).with do 
-        largest = 500
-        if existing = provider.manager.search
-                existing.each do |hash|
-                next unless value = hash[:gid]
-                num = value[0].to_i
-                if num > largest
-                    largest = num
-                end
-            end
-        end
-        largest + 1
-    end
-
-    # Convert a group name to an id.
-    def self.name2id(group)
-        return nil unless result = manager.search("cn=%s" % group) and result.length > 0
-
-        # Only use the first result.
-        group = result[0]
-        gid = group[:gid][0]
-        return gid
-    end
-end
diff --git a/lib/puppet/provider/interface/redhat.rb b/lib/puppet/provider/interface/redhat.rb
new file mode 100644
index 0000000..4a9fcb4
--- /dev/null
+++ b/lib/puppet/provider/interface/redhat.rb
@@ -0,0 +1,250 @@
+require 'puppet/provider/parsedfile'
+require 'erb'
+
+Puppet::Type.type(:interface).provide(:redhat) do
+    desc "Manage network interfaces on Red Hat operating systems.  This provider
+        parses and generates configuration files in ``/etc/sysconfig/network-scripts``."
+
+    INTERFACE_DIR = "/etc/sysconfig/network-scripts"
+    confine :exists => INTERFACE_DIR
+    defaultfor :operatingsystem => [:fedora, :centos, :redhat]
+
+    # Create the setter/gettor methods to match the model.
+    mk_resource_methods
+
+    @templates = {}
+
+    # Register a template.
+    def self.register_template(name, string)
+        @templates[name] = ERB.new(string)
+    end
+
+    # Retrieve a template by name.
+    def self.template(name)
+        @templates[name]
+    end
+
+    register_template :alias, <<-ALIAS
+DEVICE=<%= self.device %>
+ONBOOT=<%= self.on_boot %>
+BOOTPROTO=none
+IPADDR=<%= self.name %>
+NETMASK=<%= self.netmask %>
+BROADCAST=
+ALIAS
+
+
+    register_template :normal, <<-LOOPBACKDUMMY
+DEVICE=<%= self.device %>
+ONBOOT=<%= self.on_boot %>
+BOOTPROTO=static
+IPADDR=<%= self.name %>
+NETMASK=<%= self.netmask %>
+BROADCAST=
+LOOPBACKDUMMY
+
+    # maximum number of dummy interfaces
+    @max_dummies = 10
+
+    # maximum number of aliases per interface
+    @max_aliases_per_iface = 10
+
+    @@dummies = []
+    @@aliases = Hash.new { |hash, key| hash[key] = [] }
+
+    # calculate which dummy interfaces are currently already in
+    # use prior to needing to call self.next_dummy later on.
+    def self.instances
+        # parse all of the config files at once
+        Dir.glob("%s/ifcfg-*" % INTERFACE_DIR).collect do |file|
+            record = parse(file)
+
+            # store the existing dummy interfaces
+            @@dummies << record[:ifnum] if (record[:interface_type] == :dummy and ! @@dummies.include?(record[:ifnum]))
+
+            @@aliases[record[:interface]] << record[:ifnum] if record[:interface_type] == :alias
+
+            new(record)
+        end
+    end
+
+    # return the next avaliable dummy interface number, in the case where
+    # ifnum is not manually specified
+    def self.next_dummy
+        @max_dummies.times do |i|
+            unless @@dummies.include?(i.to_s)
+                @@dummies << i.to_s
+                return i.to_s
+            end
+        end
+    end
+
+    # return the next available alias on a given interface, in the case
+    # where ifnum if not manually specified
+    def self.next_alias(interface)
+        @max_aliases_per_iface.times do |i|
+            unless @@aliases[interface].include?(i.to_s)
+                @@aliases[interface] << i.to_s
+                return i.to_s
+            end
+        end
+    end
+
+    # base the ifnum, for dummy / loopback interface in linux
+    # on the last octect of the IP address
+
+    # Parse the existing file.
+    def self.parse(file)
+        instance = new()
+        return instance unless FileTest.exist?(file)
+
+        File.readlines(file).each do |line|
+            if line =~ /^(\w+)=(.+)$/
+                instance.send($1.downcase + "=", $2)
+            end
+        end
+
+        return instance
+    end
+
+    # Prefetch our interface list, yo.
+    def self.prefetch(resources)
+        instances.each do |prov|
+            if resource = resources[prov.name]
+                resource.provider = prov
+            end
+        end
+    end
+
+    def create
+        self.class.resource_type.validproperties.each do |property|
+            if value = @resource.should(property)
+                @property_hash[property] = value
+            end
+        end
+        @property_hash[:name] = @resource.name
+
+        return (@resource.class.name.to_s + "_created").intern
+    end
+
+    def destroy
+        File.unlink(file_path)
+    end
+
+    def exists?
+        FileTest.exist?(file_path)
+    end
+
+    # generate the content for the interface file, so this is dependent
+    # on whether we are adding an alias to a real interface, or a loopback
+    # address (also dummy) on linux. For linux it's quite involved, and we
+    # will use an ERB template
+    def generate
+        itype = self.interface_type == :alias ? :alias : :normal
+        self.class.template(itype).result(binding)
+    end
+
+    # Where should the file be written out?
+    # This defaults to INTERFACE_DIR/ifcfg-<namevar>, but can have a
+    # more symbolic name by setting interface_desc in the type. 
+    def file_path
+        if resource and val = resource[:interface_desc]
+            desc = val
+        else
+            desc = self.name
+        end
+
+        self.fail("Could not get name for interface") unless desc
+
+        if self.interface_type == :alias
+            return File.join(INTERFACE_DIR, "ifcfg-" + self.interface + ":" + desc)
+        else
+            return File.join(INTERFACE_DIR, "ifcfg-" + desc)
+        end
+    end
+
+    # Use the device value to figure out all kinds of nifty things.
+    def device=(value)
+        case value
+        when /:/:
+            @property_hash[:interface], @property_hash[:ifnum] = value.split(":")
+            @property_hash[:interface_type] = :alias
+        when /^dummy/:
+            @property_hash[:interface_type] = :loopback
+            @property_hash[:interface] = "dummy"
+
+            # take the number of the dummy interface, as this is used
+            # when working out whether to call next_dummy when dynamically
+            # creating these
+            @property_hash[:ifnum] = value.sub("dummy",'')
+
+            @@dummies << @property_hash[:ifnum].to_s unless @@dummies.include?(@property_hash[:ifnum].to_s)
+        else
+            @property_hash[:interface_type] = :normal
+            @property_hash[:interface] = value
+        end
+    end
+
+    # create the device name, so this based on the IP, and interface + type
+    def device
+        case @resource.should(:interface_type)
+        when :loopback
+            @property_hash[:ifnum] ||= self.class.next_dummy
+            return "dummy" + @property_hash[:ifnum]
+        when :alias
+            @property_hash[:ifnum] ||= self.class.next_alias(@resource[:interface])
+            return @resource[:interface] + ":" + @property_hash[:ifnum]
+        end
+    end
+
+    # Set the name to our ip address.
+    def ipaddr=(value)
+        @property_hash[:name] = value
+    end
+
+    # whether the device is to be brought up on boot or not. converts
+    # the true / false of the type, into yes / no values respectively
+    # writing out the ifcfg-* files
+    def on_boot
+        case @property_hash[:onboot].to_s
+        when "true"
+            return "yes"
+        when "false"
+            return "no"
+        else
+            return "neither"
+        end
+    end
+
+    # Mark whether the interface should be started on boot.
+    def on_boot=(value)
+        # translate whether we come up on boot to true/false
+        case value.downcase
+        when "yes":
+            @property_hash[:onboot] = :true
+        else
+            @property_hash[:onboot] = :false
+        end
+    end
+
+    # Write the new file out.
+    def flush
+        # Don't flush to disk if we're removing the config.
+        return if self.ensure == :absent
+
+        @property_hash.each do |name, val|
+            if val == :absent
+                raise ArgumentError, "Propety %s must be provided" % val
+            end
+        end
+
+        File.open(file_path, "w") do |f|
+            f.puts generate()
+        end
+    end
+
+    def prefetch
+        @property_hash = self.class.parse(file_path)
+    end
+end
+
diff --git a/lib/puppet/provider/interface/sunos.rb b/lib/puppet/provider/interface/sunos.rb
new file mode 100644
index 0000000..eda21ca
--- /dev/null
+++ b/lib/puppet/provider/interface/sunos.rb
@@ -0,0 +1,133 @@
+require 'puppet/provider/parsedfile'
+require 'erb'
+
+Puppet::Type.type(:interface).provide(:sunos) do
+    confine :kernel => "SunOS"
+
+    # Add accessor/getter methods for each property/parameter; these methods
+    # modify @property_hash.
+    mk_resource_methods
+
+    # Get a list of interface instances.
+    def self.instances
+		Dir.glob("/etc/hostname.*").collect do |file|
+            device = File.basename(file).split(".").pop
+
+            instance = new(:interface => device)
+            instance.parse
+            instance
+        end
+    end
+
+	def self.match(hash)
+		# see if we can match the has against an existing object
+		if model.find { |obj| obj.value(:name) == hash[:name] }
+			return obj
+        else
+            return false
+		end	
+	end
+
+    # Prefetch our interface list, yo.
+    def self.prefetch(resources)
+        instances.each do |prov|
+            if resource = resources[prov.name]
+                resource.provider = prov
+            end
+        end
+    end
+
+    def initialize(*args)
+        @property_hash = {}
+        super
+    end
+
+    def create
+        self.class.resource_type.validproperties.each do |property|
+            if value = resource.should(property)
+                @property_hash[property] = value
+            end
+        end
+        @property_hash[:name] = resource.name
+
+        return (@resource.class.name.to_s + "_created").intern
+    end
+
+    def destroy
+        File.unlink(file_path)
+        @property_hash[:ensure] = :absent
+    end
+
+    def exists?
+        FileTest.exist?(file_path)
+    end
+
+    # Where should the file be written out?  Can be overridden by setting
+    # :target in the model.
+    def file_path
+        self.fail("Could not determine interface") unless interface = @property_hash[:interface] || (resource and resource[:interface])
+       	return File.join("/etc", "hostname." + interface)
+    end
+
+    def flush
+        return if self.ensure == :absent
+        File.open(file_path, "w") { |f| f.print generate() + "\n" }
+    end
+
+    # Turn our record into a line.
+    def generate
+        ret = []
+        if self.interface_type == :alias
+            ret << "addif"
+        end
+        ret << self.name
+
+        if self.ifopts != :absent
+            if @property_hash[:ifopts].is_a?(Array)
+                ret << @property_hash[:ifopts].join(" ")
+            else
+                ret << @property_hash[:ifopts]
+            end
+        end
+
+        if self.onboot and ! [:absent, :false].include?(self.onboot)
+            ret << "up"
+        end
+
+        return ret.join(" ")
+    end
+
+    # Parse our interface file.
+    def parse
+        (@property_hash = {:ensure => :absent} and return) unless FileTest.exist?(file_path)
+
+        values = File.read(file_path).chomp.split(/\s+/)
+
+        @property_hash[:ensure] = :present
+        #@property_hash = {:ensure => :present}
+
+        # Are we the primary interface?
+        if values[0] == "addif"
+            @property_hash[:interface_type] = :alias
+            values.shift
+        else
+            @property_hash[:interface_type] = :normal
+        end
+
+        # Should the interface be up by default?
+        if values[-1] == "up"
+            @property_hash[:onboot] = :true
+            values.pop
+        else
+            @property_hash[:onboot] = :false
+        end
+
+        # Set the interface name.
+        @property_hash[:name] = values.shift
+
+        # Handle any interface options
+        unless values.empty?
+            @property_hash[:ifopts] = values.join(" ")
+        end
+    end
+end
diff --git a/lib/puppet/provider/ldap.rb b/lib/puppet/provider/ldap.rb
deleted file mode 100644
index 76834f9..0000000
--- a/lib/puppet/provider/ldap.rb
+++ /dev/null
@@ -1,137 +0,0 @@
-require 'puppet/provider'
-
-# The base class for LDAP providers.
-class Puppet::Provider::Ldap < Puppet::Provider
-    require 'puppet/util/ldap/manager'
-
-    class << self
-        attr_reader :manager
-    end
-
-    # Look up all instances at our location.  Yay.
-    def self.instances
-        return [] unless list = manager.search
-
-        list.collect { |entry| new(entry) }
-    end
-
-    # Specify the ldap manager for this provider, which is
-    # used to figure out how we actually interact with ldap.
-    def self.manages(*args)
-        @manager = Puppet::Util::Ldap::Manager.new
-        @manager.manages(*args)
-
-        # Set up our getter/setter methods.
-        mk_resource_methods
-        return @manager
-    end
-
-    # Query all of our resources from ldap.
-    def self.prefetch(resources)
-        resources.each do |name, resource|
-            if result = manager.find(name)
-                result[:ensure] = :present
-                resource.provider = new(result)
-            else
-                resource.provider = new(:ensure => :absent)
-            end
-        end
-    end
-
-    attr_reader :ldap_properties
-
-    def manager
-        self.class.manager
-    end
-
-    def create
-        @property_hash[:ensure] = :present
-        self.class.resource_type.validproperties.each do |property|
-            if val = resource.should(property)
-                @property_hash[property] = val
-            end
-        end
-    end
-
-    def delete
-        @property_hash[:ensure] = :absent
-    end
-
-    def exists?
-        @property_hash[:ensure] != :absent
-    end
-
-    # Apply our changes to ldap, yo.
-    def flush
-        # Just call the manager's update() method.
-        @property_hash.delete(:groups)
-        @ldap_properties.delete(:groups)
-        manager.update(name, ldap_properties, properties)
-        @property_hash.clear
-        @ldap_properties.clear
-    end
-
-    def initialize(*args)
-        raise(Puppet::DevError, "No LDAP Configuration defined for %s" % self.class) unless self.class.manager
-        raise(Puppet::DevError, "Invalid LDAP Configuration defined for %s" % self.class) unless self.class.manager.valid?
-        super
-
-        @property_hash = @property_hash.inject({}) do |result, ary|
-            param, values = ary
-
-            # Skip any attributes we don't manage.
-            next result unless self.class.resource_type.validattr?(param)
-
-            paramclass = self.class.resource_type.attrclass(param)
-
-            unless values.is_a?(Array)
-                result[param] = values
-                next result
-            end
-
-            # Only use the first value if the attribute class doesn't manage
-            # arrays of values.
-            if paramclass.superclass == Puppet::Parameter or paramclass.array_matching == :first
-                result[param] = values[0]
-            else
-                result[param] = values
-            end
-            result
-        end
-
-        # Make a duplicate, so that we have a copy for comparison 
-        # at the end.
-        @ldap_properties = @property_hash.dup
-    end
-
-    # Return the current state of ldap.
-    def ldap_properties
-        @ldap_properties.dup
-    end
-
-    # Return (and look up if necessary) the desired state.
-    def properties
-        if @property_hash.empty?
-            @property_hash = query || {:ensure => :absent}
-            if @property_hash.empty?
-                @property_hash[:ensure] = :absent
-            end
-        end
-        @property_hash.dup
-    end
-
-    # Collect the current attributes from ldap.  Returns
-    # the results, but also stores the attributes locally,
-    # so we have something to compare against when we update.
-    # LAK:NOTE This is normally not used, because we rely on prefetching.
-    def query
-        # Use the module function.
-        unless attributes = manager.find(name)
-            @ldap_properties = {}
-            return nil
-        end
-
-        @ldap_properties = attributes
-        return @ldap_properties.dup
-    end
-end
diff --git a/lib/puppet/provider/nameservice.rb b/lib/puppet/provider/nameservice.rb
index c1e21af..bba6c98 100644
--- a/lib/puppet/provider/nameservice.rb
+++ b/lib/puppet/provider/nameservice.rb
@@ -179,33 +179,11 @@ class Puppet::Provider::NameService < Puppet::Provider
     end
 
     def create
-       if exists?
-            info "already exists"
-            # The object already exists
-            return nil
-        end
-
-        begin
-            execute(self.addcmd)
-        rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error, "Could not create %s %s: %s" %
-                [@resource.class.name, @resource.name, detail]
-        end
+        self.ensure = :present
     end
 
     def delete
-        unless exists?
-            info "already absent"
-            # the object already doesn't exist
-            return nil
-        end
-
-        begin
-            execute(self.deletecmd)
-        rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error, "Could not delete %s %s: %s" %
-                [@resource.class.name, @resource.name, detail]
-        end
+        self.ensure = :absent
     end
 
     def ensure
@@ -216,6 +194,43 @@ class Puppet::Provider::NameService < Puppet::Provider
         end
     end
 
+    # This is only used when creating or destroying the object.
+    def ensure=(value)
+        cmd = nil
+        event = nil
+        case value
+        when :absent
+            # we need to remove the object...
+            unless exists?
+                info "already absent"
+                # the object already doesn't exist
+                return nil
+            end
+
+            # again, needs to be set by the ind. property or its
+            # parent
+            cmd = self.deletecmd
+            type = "delete"
+        when :present
+            if exists?
+                info "already exists"
+                # The object already exists
+                return nil
+            end
+
+            # blah blah, define elsewhere, blah blah
+            cmd = self.addcmd
+            type = "create"
+        end
+
+        begin
+            execute(cmd)
+        rescue Puppet::ExecutionFailure => detail
+            raise Puppet::Error, "Could not %s %s %s: %s" %
+                [type, @resource.class.name, @resource.name, detail]
+        end
+    end
+
     # Does our object exist?
     def exists?
         if getinfo(true)
@@ -308,7 +323,8 @@ class Puppet::Provider::NameService < Puppet::Provider
         begin
             execute(cmd)
         rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error, "Could not set %s on %s[%s]: %s" % [param, @resource.class.name, @resource.name, detail]
+            raise Puppet::Error, "Could not set %s on %s[%s]: %s" %
+                [param, @resource.class.name, @resource.name, detail]
         end
     end
 end
diff --git a/lib/puppet/provider/nameservice/directoryservice.rb b/lib/puppet/provider/nameservice/directoryservice.rb
index fcc44f9..e2e68b2 100644
--- a/lib/puppet/provider/nameservice/directoryservice.rb
+++ b/lib/puppet/provider/nameservice/directoryservice.rb
@@ -206,18 +206,9 @@ class DirectoryService < Puppet::Provider::NameService
         if ensure_value == :present
             @resource.class.validproperties.each do |name|
                 next if name == :ensure
-
-                # LAK: We use property.sync here rather than directly calling
-                # the settor method because the properties might do some kind
-                # of conversion.  In particular, the user gid property might
-                # have a string and need to convert it to a number
-                if @resource.should(name)
-                    @resource.property(name).sync
-                elsif value = autogen(name)
-                    self.send(name.to_s + "=", value)
-                else
-                    next
-                end
+                next unless val = @resource.should(name) || autogen(name)
+                # JJM: This calls the method.
+                self.send(name.to_s + "=", val)
             end
         end 
     end
diff --git a/lib/puppet/provider/nameservice/netinfo.rb b/lib/puppet/provider/nameservice/netinfo.rb
index ac7bc94..2960005 100644
--- a/lib/puppet/provider/nameservice/netinfo.rb
+++ b/lib/puppet/provider/nameservice/netinfo.rb
@@ -138,18 +138,8 @@ class NetInfo < Puppet::Provider::NameService
         if arg == :present
             @resource.class.validproperties.each do |name|
                 next if name == :ensure
-
-                # LAK: We use property.sync here rather than directly calling
-                # the settor method because the properties might do some kind
-                # of conversion.  In particular, the user gid property might
-                # have a string and need to convert it to a number
-                if @resource.should(name)
-                    @resource.property(name).sync
-                elsif value = autogen(name)
-                    self.send(name.to_s + "=", value)
-                else
-                    next
-                end
+                next unless val = @resource.should(name) || autogen(name)
+                self.send(name.to_s + "=", val)
             end
         end
     end
diff --git a/lib/puppet/provider/nameservice/objectadd.rb b/lib/puppet/provider/nameservice/objectadd.rb
index 256368e..8ebf892 100644
--- a/lib/puppet/provider/nameservice/objectadd.rb
+++ b/lib/puppet/provider/nameservice/objectadd.rb
@@ -2,6 +2,15 @@ require 'puppet/provider/nameservice'
 
 class Puppet::Provider::NameService
 class ObjectAdd < Puppet::Provider::NameService
+    # Does the object already exist?
+    def self.exists?(obj)
+        if obj.getinfo(true)
+            return true
+        else
+            return false
+        end
+    end
+    
     def deletecmd
         [command(:delete), @resource[:name]]
     end
@@ -13,8 +22,10 @@ class ObjectAdd < Puppet::Provider::NameService
     end
 
     def modifycmd(param, value)
-        cmd = [command(:modify), flag(param), value]
-        if @resource.allowdupe? && ((param == :uid) || (param == :gid and self.class.name == :groupadd))
+        cmd = [command(:modify),
+            flag(param),
+            value]
+        if @resource[:allowdupe]  == :true
             cmd << "-o"
         end
         cmd << @resource[:name]
@@ -30,3 +41,4 @@ class ObjectAdd < Puppet::Provider::NameService
     end
 end
 end
+
diff --git a/lib/puppet/provider/package/appdmg.rb b/lib/puppet/provider/package/appdmg.rb
index 2ee82a9..e822be1 100644
--- a/lib/puppet/provider/package/appdmg.rb
+++ b/lib/puppet/provider/package/appdmg.rb
@@ -55,7 +55,7 @@ Puppet::Type.type(:package).provide(:appdmg, :parent => Puppet::Provider::Packag
             self.fail "Mac OS X PKG DMG's must specificy a source string ending in .dmg"
         end
         require 'open-uri'
-        require 'facter/util/plist'
+        require 'puppet/util/plist'
         cached_source = source
         if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source
             cached_source = "/tmp/#{name}"
diff --git a/lib/puppet/provider/package/apt.rb b/lib/puppet/provider/package/apt.rb
index 8046512..016623d 100755
--- a/lib/puppet/provider/package/apt.rb
+++ b/lib/puppet/provider/package/apt.rb
@@ -10,7 +10,7 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
     commands :aptcache => "/usr/bin/apt-cache"
     commands :preseed => "/usr/bin/debconf-set-selections"
 
-    defaultfor :operatingsystem => [:debian, :ubuntu]
+    defaultfor :operatingsystem => :debian
 
     ENV['DEBIAN_FRONTEND'] = "noninteractive"
 
@@ -45,19 +45,9 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
         if @resource[:responsefile]
             self.run_preseed
         end
-        should = @resource[:ensure]
+        should = @resource.should(:ensure)
 
         checkforcdrom()
-        cmd = %w{-q -y}
-
-        keep = ""
-        if config = @resource[:configfiles]
-            if config == :keep
-                cmd << "-o" << 'DPkg::Options::=--force-confold'
-            else
-                cmd << "-o" << 'DPkg::Options::=--force-confnew'
-            end
-        end
 
         str = @resource[:name]
         case should
@@ -67,6 +57,19 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
             # Add the package version
             str += "=%s" % should
         end
+        cmd = %w{-q -y}
+
+        keep = ""
+        if config = @resource[:configfiles]
+            case config
+            when :keep
+                cmd << "-o" << 'DPkg::Options::=--force-confold'
+            when :replace
+                cmd << "-o" << 'DPkg::Options::=--force-confnew'
+            else
+                raise Puppet::Error, "Invalid 'configfiles' value %s" % config
+            end
+        end
 
         cmd << :install << str
         
@@ -89,7 +92,7 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
 	# preseeds answers to dpkg-set-selection from the "responsefile"
 	#
     def run_preseed
-        if response = @resource[:responsefile] and FileTest.exist?(response)
+        if response = @resource[:responsefile] and FileTest.exists?(response)
             self.info("Preseeding %s to debconf-set-selections" % response)
 
             preseed response
@@ -98,12 +101,16 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
         end
     end
 
+    def update
+        self.install
+    end
+
     def uninstall
         aptget "-y", "-q", :remove, @resource[:name]
     end
 
     def purge
-        aptget '-y', '-q', :remove, '--purge', @resource[:name]
+        aptget '-y', '-q', 'remove', '--purge', @resource[:name]
         # workaround a "bug" in apt, that already removed packages are not purged
         super
     end
diff --git a/lib/puppet/provider/package/blastwave.rb b/lib/puppet/provider/package/blastwave.rb
index a2f86aa..402e8a1 100755
--- a/lib/puppet/provider/package/blastwave.rb
+++ b/lib/puppet/provider/package/blastwave.rb
@@ -6,8 +6,6 @@ Puppet::Type.type(:package).provide :blastwave, :parent => :sun, :source => :sun
         pkgget = "/opt/csw/bin/pkg-get"
     end
 
-    confine :operatingsystem => :solaris
-
     commands :pkgget => pkgget
 
     # This is so stupid, but then, so is blastwave.
diff --git a/lib/puppet/provider/package/dpkg.rb b/lib/puppet/provider/package/dpkg.rb
index 67d31a5..512170a 100755
--- a/lib/puppet/provider/package/dpkg.rb
+++ b/lib/puppet/provider/package/dpkg.rb
@@ -23,56 +23,37 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
 
             # now turn each returned line into a package object
             process.each { |line|
-                if hash = parse_line(line)
-                    packages << new(hash)
-                end
-            }
-        end
+                if match = regex.match(line)
+                    hash = {}
 
-        return packages
-    end
+                    fields.zip(match.captures) { |field,value|
+                        hash[field] = value
+                    }
 
-    REGEX = %r{^(\S+) +(\S+) +(\S+) (\S+) (\S*)$}
-    FIELDS = [:desired, :error, :status, :name, :ensure]
+                    hash[:provider] = self.name
 
-    def self.parse_line(line)
-        if match = REGEX.match(line)
-            hash = {}
+                    if hash[:status] == 'not-installed'
+                        hash[:ensure] = :purged
+                    elsif hash[:status] != "installed"
+                        hash[:ensure] = :absent
+                    end
 
-            FIELDS.zip(match.captures) { |field,value|
-                hash[field] = value
+                    packages << new(hash)
+                else
+                    Puppet.warning "Failed to match dpkg-query line %s" %
+                        line.inspect
+                end
             }
-
-            hash[:provider] = self.name
-
-            if hash[:status] == 'not-installed'
-                hash[:ensure] = :purged
-            elsif hash[:status] != "installed"
-                hash[:ensure] = :absent
-            end
-        else
-            Puppet.warning "Failed to match dpkg-query line %s" % line.inspect
-            return nil
         end
 
-        return hash
+        return packages
     end
 
     def install
         unless file = @resource[:source]
             raise ArgumentError, "You cannot install dpkg packages without a source"
         end
-        
-        args = []
-
-        if @resource[:configfiles] == :keep
-            args << '--force-confold'
-        else
-            args << '--force-confnew'
-        end
-        args << '-i' << file
-
-        dpkg(*args)
+        dpkg "-i", file
     end
 
     def update
@@ -84,7 +65,7 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
         output = dpkg_deb "--show", @resource[:source]
         matches = /^(\S+)\t(\S+)$/.match(output).captures
         unless matches[0].match(@resource[:name])
-            warning "source doesn't contain named package, but %s" % matches[0]
+            Puppet.warning "source doesn't contain named package, but %s" % matches[0]
         end
         matches[1]
     end
@@ -107,16 +88,37 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
                 :name => @resource[:name], :error => 'ok'}
 
         end
+        # Our regex for matching dpkg-query output.  We could probably just
+        # use split here, but I'm not positive that dpkg-query will never
+        # return whitespace.
+        regex = %r{^(\S+) (\S+) (\S+) (\S+) (\S*)$}
 
-        hash = self.class.parse_line(output) || {:ensure => :absent, :status => 'missing', :name => @resource[:name], :error => 'ok'}
+        line = output.split("\n").shift.chomp
+        
+        if match = regex.match(line)
+            fields.zip(match.captures) { |field,value|
+                hash[field] = value
+            }
+        else
+            notice "Failed to handle dpkg-query line %s" % line.inspect
+            return {:ensure => :absent, :status => 'missing',
+                :name => @resource[:name], :error => 'ok'}
+        end
 
         if hash[:error] != "ok"
-            raise Puppet::Error.new(
+            raise Puppet::PackageError.new(
                 "Package %s, version %s is in error state: %s" %
                     [hash[:name], hash[:ensure], hash[:error]]
             )
         end
 
+        # DPKG can discuss packages that are no longer installed, so allow that.
+        if hash[:status] == "not-installed"
+            hash[:ensure] = :purged
+        elsif hash[:status] != "installed"
+            hash[:ensure] = :absent
+        end
+
         return hash
     end
 
@@ -128,3 +130,4 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
         dpkg "--purge", @resource[:name]
     end
 end
+
diff --git a/lib/puppet/provider/package/fink.rb b/lib/puppet/provider/package/fink.rb
index 4d56066..030e1a3 100755
--- a/lib/puppet/provider/package/fink.rb
+++ b/lib/puppet/provider/package/fink.rb
@@ -4,7 +4,7 @@ Puppet::Type.type(:package).provide :fink, :parent => :dpkg, :source => :dpkg do
 
     desc "Package management via ``fink``."
     
-    commands :fink => "/sw/bin/fink"
+	commands :fink => "/sw/bin/fink"
     commands :aptget => "/sw/bin/apt-get"
     commands :aptcache => "/sw/bin/apt-cache"
     commands :dpkgquery => "/sw/bin/dpkg-query"
diff --git a/lib/puppet/provider/package/freebsd.rb b/lib/puppet/provider/package/freebsd.rb
index 18df015..f98f306 100755
--- a/lib/puppet/provider/package/freebsd.rb
+++ b/lib/puppet/provider/package/freebsd.rb
@@ -18,22 +18,11 @@ Puppet::Type.type(:package).provide :freebsd, :parent => :openbsd do
     def install
         should = @resource.should(:ensure)
 
-        if @resource[:source] =~ /\/$/
-            if @resource[:source] =~ /^(ftp|https?):/
-                withenv :PACKAGESITE => @resource[:source] do
-                    pkgadd "-r", @resource[:name]
-                end
-            else
-                withenv :PKG_PATH => @resource[:source] do
-                    pkgadd @resource[:name]
-                end
-            end
-        else
-            if @resource[:source]
-                Puppet.warning "source is defined but does not have trailing slash, ignoring %s" % @resource[:source]
-            end
-            pkgadd "-r", @resource[:name]
+        if @resource[:source]
+            return super
         end
+
+        pkgadd "-r", @resource[:name]
     end
 
     def query
diff --git a/lib/puppet/provider/package/gem.rb b/lib/puppet/provider/package/gem.rb
index 133243c..bb09bc5 100755
--- a/lib/puppet/provider/package/gem.rb
+++ b/lib/puppet/provider/package/gem.rb
@@ -1,12 +1,9 @@
 require 'puppet/provider/package'
-require 'uri'
 
 # Ruby gems support.
 Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package do
-    desc "Ruby Gem support.  If a URL is passed via ``source``, then that URL is used as the
-         remote gem repository; if a source is present but is not a valid URL, it will be
-         interpreted as the path to a local gem file.  If source is not present at all,
-         the gem will be installed from the default gem repositories."
+    desc "Ruby Gem support.  By default uses remote gems, but you can specify
+        the path to a local gem via ``source``."
 
     has_feature :versionable
 
@@ -68,38 +65,20 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package d
     end
 
     def install(useversion = true)
-        command = [command(:gemcmd), "install"]
-        if (! resource[:ensure].is_a? Symbol) and useversion
-            command << "-v" << resource[:ensure]
+        command = ["install"]
+        if (! @resource.should(:ensure).is_a? Symbol) and useversion
+            command << "-v" << @resource.should(:ensure)
         end
         # Always include dependencies
         command << "--include-dependencies"
 
-        if source = resource[:source]
-            begin
-                uri = URI.parse(source)
-            rescue => detail
-                fail "Invalid source '%s': %s" % [uri, detail]
-            end
-
-            case uri.scheme
-            when nil: 
-                # no URI scheme => interpret the source as a local file
-                command << source
-            when /file/i
-                command << uri.path
-            when 'puppet'
-                # we don't support puppet:// URLs (yet)
-                raise Puppet::Error.new("puppet:// URLs are not supported as gem sources")              
-            else
-                # interpret it as a gem repository
-                command << "--source" << "#{source}" << resource[:name]
-            end
+        if source = @resource[:source]
+            command << source
         else
-            command << resource[:name]
+            command << @resource[:name]
         end
 
-        output = execute(command)
+        output = gemcmd(*command)
         # Apparently some stupid gem versions don't exit non-0 on failure
         if output.include?("ERROR")
             self.fail "Could not install: %s" % output.chomp
@@ -108,17 +87,17 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package d
 
     def latest
         # This always gets the latest version available.
-        hash = self.class.gemlist(:justme => resource[:name])
+        hash = self.class.gemlist(:justme => @resource[:name])
 
         return hash[:ensure]
     end
 
     def query
-        self.class.gemlist(:justme => resource[:name], :local => true)
+        self.class.gemlist(:justme => @resource[:name], :local => true)
     end
 
     def uninstall
-        gemcmd "uninstall", "-x", "-a", resource[:name]
+        gemcmd "uninstall", "-x", "-a", @resource[:name]
     end
 
     def update
diff --git a/lib/puppet/provider/package/hpux.rb b/lib/puppet/provider/package/hpux.rb
deleted file mode 100644
index 202fa24..0000000
--- a/lib/puppet/provider/package/hpux.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# HP-UX packaging.
-
-require 'puppet/provider/package'
-
-Puppet::Type.type(:package).provide :hpux, :parent => Puppet::Provider::Package do
-
-    desc "HP-UX's packaging system."
-
-    commands :swinstall => "/usr/sbin/swinstall",
-             :swlist => "/usr/sbin/swlist",
-             :swremove => "/usr/sbin/swremove"
-
-    confine :operatingsystem => "hp-ux"
-
-    defaultfor :operatingsystem => "hp-ux"
-    
-    def self.instances
-        # TODO:  This is very hard on HP-UX!
-        []
-    end
-    
-    # source and name are required
-    def install
-        raise ArgumentError, "source must be provided to install HP-UX packages" unless resource[:source]
-        args = standard_args + ["-s", resource[:source], resource[:name]]
-        swinstall(*args)
-    end
-    
-    def query
-        begin
-            swlist resource[:name]
-            {:ensure => :present}
-        rescue
-            {:ensure => :absent}
-        end
-    end
-    
-    def uninstall
-        args = standard_args + [resource[:name]]
-        swremove(*args)
-    end
-    
-    def standard_args
-        return ["-x", "mount_all_filesystems=false"]
-    end
-end
diff --git a/lib/puppet/provider/package/pkgdmg.rb b/lib/puppet/provider/package/pkgdmg.rb
index fa546c6..2614d09 100644
--- a/lib/puppet/provider/package/pkgdmg.rb
+++ b/lib/puppet/provider/package/pkgdmg.rb
@@ -28,7 +28,66 @@
 require 'puppet/provider/package'
 
 Puppet::Type.type(:package).provide :pkgdmg, :parent => Puppet::Provider::Package do
-    desc "Package management based on Apple's Installer.app and DiskUtility.app.  This package works by checking the contents of a DMG image for Apple pkg or mpkg files. Any number of pkg or mpkg files may exist in the root directory of the DMG file system. Sub directories are not checked for packages.  See `the wiki docs </trac/puppet/wiki/DmgPackages>` for more detail."
+    desc "Package management based on Apple's Installer.app and DiskUtility.app
+    
+Author: Jeff McCune <jeff at northstarlabs.net>
+
+Please direct questions about this provider to the puppet-users mailing list.
+
+This package works by checking the contents of a DMG image for Apple pkg or
+mpkg files. Any number of pkg or mpkg files may exist in the root directory of
+the DMG file system. Sub directories are not checked for packages.
+
+This provider always assumes the label (formerly called 'name') attribute
+declared in the manifest will always exactly match the file name (without
+path) of the DMG file itself. Therefore, if you want to install packages in
+'Foobar.pkg.dmg' you must explicitly specify the label::
+
+    package { Foobar.pkg.dmg: ensure => installed, provider => pkgdmg }
+
+Only the dmg file name itself is used when puppet determines if the packages
+contained within are currently installed. For example, if a package resource
+named 'Foobar.pkg.dmg' is named for installation and contains multiple
+packages, this provider will install all packages in the root directory of
+this file system, then create a small cookie for the whole bundle, located at
+/var/db/.puppet_pkgdmg_installed_Foobar.pkg.dmg
+
+As a result, if you change the contents of the DMG file in any way, Puppet
+will not update or re-install the packages contained within unless you change
+the file name of the DMG wrapper itself. Therefore, if you use this provider,
+I recommend you name the DMG wrapper files in a manner that lends itself to
+incremental version changes. I include some version or date string in the DMG
+name, like so::
+
+    Firefox-2.0.0.3-1.pkg.dmg
+
+If I realize I've mis-packaged this DMG, then I have the option to increment
+the package version, yielding Firefox-2.0.0.3-2.pkg.dmg.
+
+This provider allows you to host DMG files within an FTP or HTTP server. This
+is primarily how the author provider distributes software. Any URL mechanism
+curl or Ruby's open-uri module supports is supported by this provider. Curl
+supported URL's yield much faster data throughput than open-uri, so I
+recommend HTTP, HTTPS, or FTP for source package repositories.
+
+Because the provider assumes packages will be transfered via CURL, a two stage
+process occurs. First, if a URL is detected, curl is invoked to transfer the
+file into a temporary directory. If no URL is present, the provider skips
+straight to step 2. In step two, the source file is mounted, then packages
+installed, and finally the DMG file is removed.
+
+If this is a problem for you, please patch the code, or bug Jeff to fix this.
+
+Example usage::
+
+    package { Thunderbird-2.0.0.4-1.pkg.dmg:
+      provider => pkgdmg, ensure => present
+      source => 'http://0.0.0.0:8000/packages/Thunderbird-2.0.0.4-1.pkg.dmg',
+    }
+
+**WARNING**: Because I assume files will be downloaded to /tmp, the current
+implementation attempts to delete DMG files if you install directly from the
+file system and not via a URL method."
   
     confine :exists => "/Library/Receipts"
     commands :installer => "/usr/sbin/installer"
@@ -70,7 +129,7 @@ Puppet::Type.type(:package).provide :pkgdmg, :parent => Puppet::Provider::Packag
             self.fail "Mac OS X PKG DMG's must specificy a source string ending in .dmg"
         end
         require 'open-uri'
-        require 'facter/util/plist'
+        require 'puppet/util/plist'
         cached_source = source
         if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source
             cached_source = "/tmp/#{name}"
diff --git a/lib/puppet/provider/package/portage.rb b/lib/puppet/provider/package/portage.rb
index ae7194f..f795d03 100644
--- a/lib/puppet/provider/package/portage.rb
+++ b/lib/puppet/provider/package/portage.rb
@@ -7,8 +7,6 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
 
     commands :emerge => "/usr/bin/emerge", :eix => "/usr/bin/eix", :update_eix => "/usr/bin/update-eix"
 
-    confine :operatingsystem => :gentoo
-
     defaultfor :operatingsystem => :gentoo
 
     def self.instances
@@ -72,7 +70,7 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
         result_format = /(\S+) (\S+) \[(?:([0-9.a-zA-Z]+(?:_(?:alpha|beta|pre|rc|p)[0-9]*)*(?:-r[0-9]*)?)(?:\([^\)]+\))?(?:\[([^\]]+)\])?[ ]*)*\] \[(?:(?:\{M\})?(?:\([~*]+\))?([0-9.a-zA-Z]+(?:_(?:alpha|beta|pre|rc|p)[0-9]*)*(?:-r[0-9]*)?)(?:\(([^\)]+)\))?(?:![mf])*(?:\[([^\]]+)\])?)?\] ([\S]*) (.*)/
         result_fields = [:category, :name, :ensure, :ensure_overlay, :version_available, :slot, :overlay, :vendor, :description]
 
-        search_field = package_name.count('/') > 0 ? "--category-name" : "--name"
+        search_field = @resource[:category] ? "--category-name" : "--name"
         search_value = package_name
         search_format = "<category> <name> [<installedversionsshort>] [<best>] <homepage> <description>"
 
diff --git a/lib/puppet/provider/package/ports.rb b/lib/puppet/provider/package/ports.rb
index 96ef3f0..1cff300 100755
--- a/lib/puppet/provider/package/ports.rb
+++ b/lib/puppet/provider/package/ports.rb
@@ -33,7 +33,7 @@ Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :fre
         begin
             output = portversion(*cmd)
         rescue Puppet::ExecutionFailure
-            raise Puppet::Error.new(output)
+            raise Puppet::PackageError.new(output)
         end
         line = output.split("\n").pop
 
@@ -47,7 +47,7 @@ Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :fre
         info = $3
 
         unless pkgstuff =~ /^(\S+)-([^-\s]+)$/
-            raise Puppet::Error,
+            raise Puppet::PackageError,
                 "Could not match package info '%s'" % pkgstuff
         end
 
@@ -61,7 +61,7 @@ Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :fre
         # Else, we need to be updated; we need to pull out the new version
 
         unless info =~ /\((\w+) has (.+)\)/
-            raise Puppet::Error,
+            raise Puppet::PackageError,
                 "Could not match version info '%s'" % info
         end
 
@@ -72,13 +72,8 @@ Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :fre
     end
 
     def query
-        # support portorigin_glob such as "mail/postfix"
-        name = self.name
-        if name =~ /\//
-            name = self.name.split(/\//).slice(1)
-        end
         self.class.instances.each do |instance|
-            if instance.name == name
+            if instance.name == self.name
                 return instance.properties
             end
         end
diff --git a/lib/puppet/provider/package/rpm.rb b/lib/puppet/provider/package/rpm.rb
index b5a5c5d..98ca1ef 100755
--- a/lib/puppet/provider/package/rpm.rb
+++ b/lib/puppet/provider/package/rpm.rb
@@ -23,16 +23,9 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
     def self.instances
         packages = []
 
-        # rpm < 4.1 don't support --nosignature
-        output = rpm "--version"
-        sig = "--nosignature"
-        if output =~ /RPM version (([123].*)|(4\.0.*))/
-            sig = ""
-        end
-
         # list out all of the packages
         begin
-            execpipe("#{command(:rpm)} -qa #{sig} --nodigest --qf '#{NEVRAFORMAT}\n'") { |process|
+            execpipe("#{command(:rpm)} -qa --nosignature --nodigest --qf '#{NEVRAFORMAT}\n'") { |process|
                 # now turn each returned line into a package object
                 process.each { |line|
                     hash = nevra_to_hash(line)
@@ -50,20 +43,19 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
     # a hash with entries :instance => fully versioned package name, and 
     # :ensure => version-release
     def query
-        #NOTE: Prior to a fix for issue 1243, this method potentially returned a cached value
-        #IF YOU CALL THIS METHOD, IT WILL CALL RPM
-        #Use get(:property) to check if cached values are available 
-        cmd = ["-q", @resource[:name], "--nosignature", "--nodigest", "--qf", "#{NEVRAFORMAT}\n"]
-
-        begin
-            output = rpm(*cmd)
-        rescue Puppet::ExecutionFailure
-            return nil
+        unless @property_hash[:epoch]
+            cmd = ["-q", @resource[:name], "--nosignature", "--nodigest", "--qf", "#{NEVRAFORMAT}\n"]
+
+            begin
+                output = rpm(*cmd)
+            rescue Puppet::ExecutionFailure
+                return nil
+            end
+            
+            # FIXME: We could actually be getting back multiple packages
+            # for multilib
+            @property_hash.update(self.class.nevra_to_hash(output))
         end
-        
-        # FIXME: We could actually be getting back multiple packages
-        # for multilib
-        @property_hash.update(self.class.nevra_to_hash(output))
 
         return @property_hash.dup
     end
@@ -75,7 +67,7 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
         end
         
         cmd = [command(:rpm), "-q", "--qf", "#{NEVRAFORMAT}\n", "-p", "#{@resource[:source]}"]
-        h = self.class.nevra_to_hash(execfail(cmd, Puppet::Error))
+        h = nevra_to_hash(execfail(cmd, Puppet::Error))
         return h[:ensure]
     end
 
diff --git a/lib/puppet/provider/package/rug.rb b/lib/puppet/provider/package/rug.rb
index 1e1d676..c5451ad 100644
--- a/lib/puppet/provider/package/rug.rb
+++ b/lib/puppet/provider/package/rug.rb
@@ -5,8 +5,8 @@ Puppet.type(:package).provide :rug, :parent => :rpm do
 
     commands :rug => "/usr/bin/rug"
     commands :rpm => "rpm"
-    defaultfor :operatingsystem => [:suse, :sles]
-    confine    :operatingsystem => [:suse, :sles]
+    defaultfor :operatingsystem => :suse 
+    confine    :operatingsystem => :suse
 
     # Install a package using 'rug'.
     def install
diff --git a/lib/puppet/provider/package/sun.rb b/lib/puppet/provider/package/sun.rb
index 0d36638..927596d 100755
--- a/lib/puppet/provider/package/sun.rb
+++ b/lib/puppet/provider/package/sun.rb
@@ -9,8 +9,6 @@ Puppet::Type.type(:package).provide :sun, :parent => Puppet::Provider::Package d
              :pkgadd => "/usr/sbin/pkgadd",
              :pkgrm => "/usr/sbin/pkgrm"
 
-    confine :operatingsystem => :solaris
-
     defaultfor :operatingsystem => :solaris
 
     def self.instances
diff --git a/lib/puppet/provider/package/sunfreeware.rb b/lib/puppet/provider/package/sunfreeware.rb
index d7bcd09..8b573fe 100755
--- a/lib/puppet/provider/package/sunfreeware.rb
+++ b/lib/puppet/provider/package/sunfreeware.rb
@@ -4,8 +4,5 @@ Puppet::Type.type(:package).provide :sunfreeware, :parent => :blastwave, :source
         At this point, support is exactly the same as ``blastwave`` support and
         has not actually been tested."
     commands :pkgget => "pkg-get"
-
-    confine :operatingsystem => :solaris
-
 end
 
diff --git a/lib/puppet/provider/package/urpmi.rb b/lib/puppet/provider/package/urpmi.rb
index a958352..8adc62a 100644
--- a/lib/puppet/provider/package/urpmi.rb
+++ b/lib/puppet/provider/package/urpmi.rb
@@ -1,6 +1,6 @@
 Puppet::Type.type(:package).provide :urpmi, :parent => :rpm, :source => :rpm do
     desc "Support via ``urpmi``."
-    commands :urpmi => "urpmi", :urpmq => "urpmq", :rpm => "rpm"
+    commands :urpmi => "urpmi", :rpm => "rpm"
 
     if command('rpm')
         confine :true => begin
@@ -41,9 +41,9 @@ Puppet::Type.type(:package).provide :urpmi, :parent => :rpm, :source => :rpm do
 
     # What's the latest package version available?
     def latest
-        output = urpmq "-S", @resource[:name]
+        output = urpmi "-S",  :available, @resource[:name]
 
-        if output =~ /^#{@resource[:name]}\s+:\s+.*\(\s+(\S+)\s+\)/
+        if output =~ /^#{@resource[:name]}\S+\s+(\S+)\s/
             return $1
         else
             # urpmi didn't find updates, pretend the current
diff --git a/lib/puppet/provider/package/yum.rb b/lib/puppet/provider/package/yum.rb
index 56fad1a..7998b92 100755
--- a/lib/puppet/provider/package/yum.rb
+++ b/lib/puppet/provider/package/yum.rb
@@ -7,7 +7,9 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
     
     YUMHELPER = File::join(File::dirname(__FILE__), "yumhelper.py")
 
-    attr_accessor :latest_info
+    class << self
+        attr_reader :updates
+    end
 
     if command('rpm')
         confine :true => begin
@@ -22,32 +24,22 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
     defaultfor :operatingsystem => [:fedora, :centos, :redhat]
 
     def self.prefetch(packages)
+        @updates = {}
         if Process.euid != 0
             raise Puppet::Error, "The yum provider can only be used as root"
         end
         super
-        return unless packages.detect { |name, package| package.should(:ensure) == :latest }
-
-         # collect our 'latest' info
-         updates = {}
-         python(YUMHELPER).each_line do |l|
-             l.chomp!
-             next if l.empty?
-             if l[0,4] == "_pkg"
-                 hash = nevra_to_hash(l[5..-1])
-                 [hash[:name], "#{hash[:name]}.#{hash[:arch]}"].each  do |n|
-                     updates[n] ||= []
-                     updates[n] << hash
-                 end
-             end
-         end
-
-         # Add our 'latest' info to the providers.
-         packages.each do |name, package|
-             if info = updates[package[:name]]
-                 package.provider.latest_info = info[0]
-             end
-         end
+        python(YUMHELPER).each_line do |l|
+            l.chomp!
+            next if l.empty?
+            if l[0,4] == "_pkg"
+                hash = nevra_to_hash(l[5..-1])
+                [hash[:name], "#{hash[:name]}.#{hash[:arch]}"].each do |n|
+                    @updates[n] ||= []
+                    @updates[n] << hash
+                end
+            end
+        end
     end
 
     def install
@@ -81,10 +73,11 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
 
     # What's the latest package version available?
     def latest
-        upd = latest_info
+        upd = self.class.updates[@resource[:name]]
         unless upd.nil?
             # FIXME: there could be more than one update for a package
             # because of multiarch
+            upd = upd[0]
             return "#{upd[:version]}-#{upd[:release]}"
         else
             # Yum didn't find updates, pretend the current
diff --git a/lib/puppet/provider/package/yumhelper.py b/lib/puppet/provider/package/yumhelper.py
index 8eab0d0..962b96c 100644
--- a/lib/puppet/provider/package/yumhelper.py
+++ b/lib/puppet/provider/package/yumhelper.py
@@ -4,23 +4,8 @@
 # (C) 2007 Red Hat Inc.
 # David Lutterkort <dlutter @redhat.com>
 
+import yum
 import sys
-import string
-import re
-
-# this maintains compatibility with really old platforms with python 1.x
-from os import popen, WEXITSTATUS
-
-# Try to use the yum libraries by default, but shell out to the yum executable
-# if they are not present (i.e. yum <= 2.0). This is only required for RHEL3
-# and earlier that do not support later versions of Yum. Once RHEL3 is EOL,
-# shell_out() and related code can be removed.
-try:
-    import yum
-except ImportError:
-    useyumlib = 0
-else:
-    useyumlib = 1
 
 OVERRIDE_OPTS = {
     'debuglevel': 0,
@@ -41,80 +26,14 @@ def pkg_lists(my):
     my.doRpmDBSetup()
     return my.doPackageLists('updates')
 
-def shell_out():
-    try:
-        p = popen("/usr/bin/env yum check-update 2>&1")
-        output = p.readlines()
-        rc = p.close()
-
-        if rc is not None:
-            # None represents exit code of 0, otherwise the exit code is in the
-            # format returned by wait(). Exit code of 100 from yum represents
-            # updates available.
-            if WEXITSTATUS(rc) != 100:
-                return WEXITSTATUS(rc)
-        else:
-            # Exit code is None (0), no updates waiting so don't both parsing output
-            return 0 
-
-        # Yum prints a line of hyphens (old versions) or a blank line between
-        # headers and package data, so skip everything before them
-        skipheaders = 0
-        for line in output:
-            if not skipheaders:
-                if re.compile("^((-){80}|)$").search(line):
-                    skipheaders = 1
-                continue
-
-            # Skip any blank lines
-            if re.compile("^[ \t]*$").search(line):
-                continue
-
-            # Format is:
-            # Yum 1.x: name arch (epoch:)?version
-            # Yum 2.0: name arch (epoch:)?version repo
-            # epoch is optional if 0
-
-            p = string.split(line)
-            pname = p[0]
-            parch = p[1]
-            pevr = p[2]
-
-            # Separate out epoch:version-release
-            evr_re = re.compile("^(\d:)?(\S+)-(\S+)$")
-            evr = evr_re.match(pevr)
-
-            pepoch = ""
-            if evr.group(1) is None:
-                pepoch = "0"
-            else:
-                pepoch = evr.group(1).replace(":", "")
-            pversion = evr.group(2)
-            prelease = evr.group(3)
-
-            print "_pkg", pname, pepoch, pversion, prelease, parch
-
-        return 0
-    except:
-        print sys.exc_info()[0]
-        return 1
-
-if useyumlib:
+try:
     try:
-        try:
-            my = yum.YumBase()
-            ypl = pkg_lists(my)
-            for pkg in ypl.updates:
-                print "_pkg %s %s %s %s %s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
-        finally:
-            my.closeRpmDB()
-    except IOError, e:
-        print "_err IOError %d %s" % (e.errno, e)
-        sys.exit(1)
-    except AttributeError, e:
-        # catch yumlib errors in buggy 2.x versions of yum
-        print "_err AttributeError %s" % e
-        sys.exit(1)
-else:
-    rc = shell_out()
-    sys.exit(rc)
+        my = yum.YumBase()
+        ypl = pkg_lists(my)
+        for pkg in ypl.updates:
+            print "_pkg %s %s %s %s %s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
+    finally:
+        my.closeRpmDB()
+except IOError, e:
+    print "_err IOError %d %s" % (e.errno, e)
+    sys.exit(1)
diff --git a/lib/puppet/provider/selboolean/getsetsebool.rb b/lib/puppet/provider/selboolean/getsetsebool.rb
deleted file mode 100644
index 4614c6c..0000000
--- a/lib/puppet/provider/selboolean/getsetsebool.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-Puppet::Type.type(:selboolean).provide(:getsetsebool) do
-    desc "Manage SELinux booleans using the getsebool and setsebool binaries."
-
-    commands :getsebool => "/usr/sbin/getsebool"
-    commands :setsebool => "/usr/sbin/setsebool"
-
-    def value
-        self.debug "Retrieving value of selboolean #{@resource[:name]}"
-
-        status = getsebool(@resource[:name])
-
-        if status =~ / off$/ then
-            return :off
-        elsif status =~ / on$/ then
-            return :on
-        else
-            status.chomp!
-            raise Puppet::Error, "Invalid response '%s' returned from getsebool" % [status]
-        end
-    end
-
-    def value=(new)
-        persist = ""
-        if @resource[:persistent] == :true
-            self.debug "Enabling persistence"
-            persist = "-P"
-        end
-        execoutput("#{command(:setsebool)} #{persist} #{@resource[:name]} #{new}")
-        return :file_changed
-    end
-
-    # Required workaround, since SELinux policy prevents setsebool
-    # from writing to any files, even tmp, preventing the standard
-    # 'setsebool("...")' construct from working.
-
-    def execoutput (cmd)
-      output = ''
-      begin
-        execpipe(cmd) do |out|
-          output = out.readlines.join('').chomp!
-        end
-      rescue Puppet::ExecutionFailure
-        raise Puppet::ExecutionFailure, output.split("\n")[0]
-      end
-      return output
-    end
-end
diff --git a/lib/puppet/provider/selmodule/semodule.rb b/lib/puppet/provider/selmodule/semodule.rb
deleted file mode 100644
index 4981366..0000000
--- a/lib/puppet/provider/selmodule/semodule.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-Puppet::Type.type(:selmodule).provide(:semodule) do
-    desc "Manage SELinux policy modules using the semodule binary."
-
-    commands :semodule => "/usr/sbin/semodule"
-
-    def create
-        begin
-            execoutput("#{command(:semodule)} --install #{selmod_name_to_filename}")
-        rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error, "Could not load policy module: %s" % [detail];
-        end
-        return :true
-    end
-
-    def destroy
-        begin
-            execoutput("#{command(:semodule)} --remove #{@resource[:name]}")
-        rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error, "Could not remove policy module: %s" % [detail];
-        end
-    end
-
-    def exists?
-        self.debug "Checking for module #{@resource[:name]}"
-        execpipe("#{command(:semodule)} --list") do |out|
-            out.each do |line|
-                if line =~ /#{@resource[:name]}\b/
-                        return :true
-                end
-            end
-        end
-        return nil
-    end
-
-    def syncversion
-        self.debug "Checking syncversion on #{@resource[:name]}"
-
-        loadver = selmodversion_loaded
-
-        if(loadver) then
-            filever = selmodversion_file
-            if (filever == loadver) then
-                return :true
-            end
-        end
-        return :false
-    end
-    
-    def syncversion= (dosync)
-        begin
-            execoutput("#{command(:semodule)} --upgrade #{selmod_name_to_filename}")
-        rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error, "Could not upgrade policy module: %s" % [detail];
-        end
-    end
-
-    # Helper functions
-
-    def execoutput (cmd)
-      output = ''
-      begin
-        execpipe(cmd) do |out|
-          output = out.readlines.join('').chomp!
-        end
-      rescue Puppet::ExecutionFailure
-        raise Puppet::ExecutionFailure, output.split("\n")[0]
-      end
-      return output
-    end
-
-    def selmod_name_to_filename
-        if @resource[:selmodulepath]
-            return @resource[:selmodulepath]
-        else
-            return "#{@resource[:selmoduledir]}/#{@resource[:name]}.pp"
-        end
-    end
-
-    def selmod_readnext (handle)
-        len = handle.read(4).unpack('L')[0]
-        return handle.read(len)
-    end
-
-    def selmodversion_file
-        magic = 0xF97CFF8F
-
-        filename = selmod_name_to_filename
-        mod = File.new(filename, "r")
-
-        (hdr, ver, numsec) = mod.read(12).unpack('LLL')
-
-        if hdr != magic
-            raise Puppet::Error, "Found #{hdr} instead of magic #{magic} in #{filename}"
-        end
-
-        if ver != 1
-            raise Puppet::Error, "Unknown policy file version #{ver} in #{filename}"
-        end
-
-        # Read through (and throw away) the file section offsets, and also
-        # the magic header for the first section.
-
-        mod.read((numsec + 1) * 4)
-
-        ## Section 1 should be "SE Linux Module"
-
-        selmod_readnext(mod)
-        selmod_readnext(mod)
-
-        # Skip past the section headers
-        mod.read(14)
-
-        # Module name
-        selmod_readnext(mod)
-
-        # At last!  the version
-
-        v = selmod_readnext(mod) 
-
-        self.debug "file version #{v}"
-        return v
-    end
-
-    def selmodversion_loaded 
-        lines = ()
-        begin
-            execpipe("#{command(:semodule)} --list") do |output|
-                lines = output.readlines
-                lines.each do |line|
-                    line.chomp!
-                    bits = line.split
-                    if bits[0] == @resource[:name] then
-                        self.debug "load version #{bits[1]}"
-                        return bits[1]
-                    end
-                end
-            end
-        rescue Puppet::ExecutionFailure
-            raise Puppet::ExecutionFailure, "Could not list policy modules: %s" % [lines.join(' ').chomp!]
-        end
-        return nil
-    end
-end
diff --git a/lib/puppet/provider/service/base.rb b/lib/puppet/provider/service/base.rb
index 8964322..254b4fe 100755
--- a/lib/puppet/provider/service/base.rb
+++ b/lib/puppet/provider/service/base.rb
@@ -1,10 +1,10 @@
 Puppet::Type.type(:service).provide :base do
     desc "The simplest form of service support.  You have to specify
         enough about your service for this to work; the minimum you can specify
-        is a binary for starting the process, and this same binary will be 
-        searched for in the process table to stop the service.  It is 
-        preferable to specify start, stop, and status commands, akin to how you
-        would do so using ``init``."
+        is a binary for starting the process, and this same binary will be searched
+        for in the process table to stop the service.  It is preferable to
+        specify start, stop, and status commands, akin to how you would do
+        so using ``init``."
 
     commands :kill => "kill"
 
diff --git a/lib/puppet/provider/service/daemontools.rb b/lib/puppet/provider/service/daemontools.rb
deleted file mode 100644
index 52d8c6b..0000000
--- a/lib/puppet/provider/service/daemontools.rb
+++ /dev/null
@@ -1,154 +0,0 @@
-# Daemontools service management
-#
-# author Brice Figureau <brice-puppet at daysofwonder.com>
-Puppet::Type.type(:service).provide :daemontools, :parent => :base do
-    desc "Daemontools service management.
-    This provider manages daemons running supervised by D.J.Bernstein daemontools.
-    It tries to detect the service directory, with by order of preference:
-     * /service
-     * /etc/service
-     * /var/lib/svscan
-    The daemon directory should be placed in a directory that can be 
-    by default in:
-     * /var/lib/service
-     * /etc
-    or this can be overriden in the service resource parameters:
-    service {
-     \"myservice\":
-       provider => \"daemontools\", path => \"/path/to/daemons\";
-    }
-
-    This provider supports out of the box:
-     * start/stop (mapped to enable/disable)
-     * enable/disable
-     * restart
-     * status"
-
-    commands :svc  => "/usr/bin/svc"
-    commands :svstat => "/usr/bin/svstat"
-
-    class << self
-        attr_writer :defpath
-        
-        # this is necessary to autodetect a valid resource
-        # default path, since there is no standard for such directory.
-        def defpath
-            unless defined?(@defpath) and @defpath
-                ["/var/lib/service", "/etc"].each do |path|
-                    if FileTest.exist?(path)
-                        @defpath = path
-                        break
-                    end
-                end
-                raise "Could not find the daemon directory (tested [/var/lib/service,/etc])" unless @defpath
-            end
-            @defpath
-        end
-    end
-
-    attr_writer :servicedir
-
-    # returns all providers for all existing services in @defpath
-    # ie enabled or not
-    def self.instances
-        path = self.defpath
-        unless FileTest.directory?(path)
-            Puppet.notice "Service path %s does not exist" % path
-            next
-        end
-
-        # reject entries that aren't either a directory
-        # or don't contain a run file
-        Dir.entries(path).reject { |e|
-            fullpath = File.join(path, e)
-            e =~ /^\./ or ! FileTest.directory?(fullpath) or ! FileTest.exist?(File.join(fullpath,"run"))
-        }.collect do |name|
-            new(:name => name, :path => path)
-        end
-    end
-
-    # returns the daemon dir on this node
-    def self.daemondir
-        self.defpath
-    end
-
-    # find the service dir on this node
-    def servicedir
-      unless defined?(@servicedir) and @servicedir
-        ["/service", "/etc/service","/var/lib/svscan"].each do |path|
-            if FileTest.exist?(path)
-                @servicedir = path
-                break
-            end
-        end
-        raise "Could not find service directory" unless @servicedir
-      end
-      @servicedir
-    end
-
-    # returns the full path of this service when enabled
-    # (ie in the service directory)
-    def service
-        File.join(self.servicedir, resource[:name])
-    end
-
-    # returns the full path to the current daemon directory
-    # note that this path can be overriden in the resource
-    # definition
-    def daemon
-        File.join(resource[:path], resource[:name])
-    end
-    
-    def restartcmd
-        [ command(:svc), "-t", self.service]
-    end
-
-    # The start command does nothing, service are automatically started
-    # when enabled by svscan. But, forces an enable if necessary
-    def start
-        # to start make sure the sevice is enabled
-        self.enable
-        # start is then automatic
-    end
-
-    def status
-        begin
-            output = svstat self.service
-            return :running if output =~ /\bup\b/
-        rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error.new( "Could not get status for service %s: %s" % [ resource.ref, detail] )
-        end
-        return :stopped
-    end
-
-    # unfortunately it is not possible
-    # to stop without disabling the service
-    def stop
-        self.disable
-    end
-
-    # disable by stopping the service
-    # and removing the symlink so that svscan
-    # doesn't restart our service behind our back
-    def disable
-        # should stop the service
-        # stop the log subservice if any
-        log = File.join(self.service, "log")
-        texecute("stop log", [ command(:svc) , '-dx', log] ) if FileTest.directory?(log)
-        
-        # stop the main resource
-        texecute("stop", [command(:svc), '-dx', self.service] )
-
-        # unlink the daemon symlink to disable it
-        File.unlink(self.service) if FileTest.symlink?(self.service)
-    end
-
-    def enabled?
-        FileTest.symlink?(self.service)
-    end
-
-    def enable
-        File.symlink(self.daemon, self.service) if ! FileTest.symlink?(self.service)
-    end
-end
-
diff --git a/lib/puppet/provider/service/debian.rb b/lib/puppet/provider/service/debian.rb
index ca433cb..da38c10 100755
--- a/lib/puppet/provider/service/debian.rb
+++ b/lib/puppet/provider/service/debian.rb
@@ -5,7 +5,7 @@ Puppet::Type.type(:service).provide :debian, :parent => :init do
         is that this supports service enabling and disabling via ``update-rc.d``."
 
     commands :update => "/usr/sbin/update-rc.d"
-    defaultfor :operatingsystem => [:debian, :ubuntu]
+    defaultfor :operatingsystem => :debian
 
     def self.defpath
         superclass.defpath
diff --git a/lib/puppet/provider/service/freebsd.rb b/lib/puppet/provider/service/freebsd.rb
index 95bde77..e5d0453 100644
--- a/lib/puppet/provider/service/freebsd.rb
+++ b/lib/puppet/provider/service/freebsd.rb
@@ -2,8 +2,6 @@
 Puppet::Type.type(:service).provide :freebsd, :parent => :init do
     desc "FreeBSD's (and probably NetBSD?) form of ``init``-style service
         management; uses ``rc.conf.d`` for service enabling and disabling."
- 
-    confine :operatingsystem => [:freebsd, :netbsd, :openbsd]
 
     defaultfor :operatingsystem => :freebsd
 
diff --git a/lib/puppet/provider/service/gentoo.rb b/lib/puppet/provider/service/gentoo.rb
index c5ba7b5..adbee69 100644
--- a/lib/puppet/provider/service/gentoo.rb
+++ b/lib/puppet/provider/service/gentoo.rb
@@ -6,8 +6,6 @@ Puppet::Type.type(:service).provide :gentoo, :parent => :init do
 
     commands :update => "/sbin/rc-update"
 
-    confine :operatingsystem => :gentoo
-
     defaultfor :operatingsystem => :gentoo
 
     def self.defpath
diff --git a/lib/puppet/provider/service/init.rb b/lib/puppet/provider/service/init.rb
index e95fbd0..274c334 100755
--- a/lib/puppet/provider/service/init.rb
+++ b/lib/puppet/provider/service/init.rb
@@ -2,9 +2,9 @@
 # customizations of this module.
 Puppet::Type.type(:service).provide :init, :parent => :base do
     desc "Standard init service management.  This provider assumes that the
-        init script has no ``status`` command, because so few scripts do,
-        so you need to either provide a status command or specify via 
-        ``hasstatus`` that one already exists in the init script."
+        init script has not ``status`` command, because so few scripts do,
+        so you need to either provide a status command or specify via ``hasstatus``
+        that one already exists in the init script."
 
     class << self
         attr_accessor :defpath
@@ -13,8 +13,6 @@ Puppet::Type.type(:service).provide :init, :parent => :base do
     case Facter["operatingsystem"].value
     when "FreeBSD":
         @defpath = ["/etc/rc.d", "/usr/local/etc/rc.d"]
-    when "HP-UX":
-        @defpath = "/sbin/init.d"
     else
         @defpath = "/etc/init.d"
     end
diff --git a/lib/puppet/provider/service/redhat.rb b/lib/puppet/provider/service/redhat.rb
index faa7547..b013c34 100755
--- a/lib/puppet/provider/service/redhat.rb
+++ b/lib/puppet/provider/service/redhat.rb
@@ -1,12 +1,12 @@
-# Manage Red Hat services.  Start/stop uses /sbin/service and enable/disable uses chkconfig
-
+# Manage debian services.  Start/stop is the same as InitSvc, but enable/disable
+# is special.
 Puppet::Type.type(:service).provide :redhat, :parent => :init do
     desc "Red Hat's (and probably many others) form of ``init``-style service
         management; uses ``chkconfig`` for service enabling and disabling."
 
-    commands :chkconfig => "/sbin/chkconfig", :service => "/sbin/service"
- 
-    defaultfor :operatingsystem => [:redhat, :fedora, :suse, :centos, :sles]
+    commands :chkconfig => "/sbin/chkconfig"
+
+    defaultfor :operatingsystem => [:redhat, :fedora, :suse, :centos]
 
     def self.defpath
         superclass.defpath
@@ -16,6 +16,7 @@ Puppet::Type.type(:service).provide :redhat, :parent => :init do
     def disable
         begin
             output = chkconfig(@resource[:name], :off)
+            output += chkconfig("--del", @resource[:name])
         rescue Puppet::ExecutionFailure
             raise Puppet::Error, "Could not disable %s: %s" %
                 [self.name, output]
@@ -42,41 +43,12 @@ Puppet::Type.type(:service).provide :redhat, :parent => :init do
     # in the init scripts.
     def enable
         begin
-            output = chkconfig(@resource[:name], :on)
+            output = chkconfig("--add", @resource[:name])
+            output += chkconfig(@resource[:name], :on)
         rescue Puppet::ExecutionFailure => detail
             raise Puppet::Error, "Could not enable %s: %s" %
                 [self.name, detail]
         end
     end
- 
-    def restart
-        if @resource[:hasrestart] == :true
-              service(@resource[:name], "restart")
-        else
-           super
-        end
-    end
-
-    def status
-        if @resource[:hasstatus] == :true
-              begin 
-                  service(@resource[:name], "status")
-                  return :running
-              rescue 
-                  return :stopped
-              end 
-        else
-           super
-        end
-    end
-
-    def start
-        service(@resource[:name], "start")
-    end
-
-    def stop
-        service(@resource[:name], "stop")
-    end
-
 end
 
diff --git a/lib/puppet/provider/service/runit.rb b/lib/puppet/provider/service/runit.rb
deleted file mode 100644
index 230fa75..0000000
--- a/lib/puppet/provider/service/runit.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# Daemontools service management
-#
-# author Brice Figureau <brice-puppet at daysofwonder.com>
-Puppet::Type.type(:service).provide :runit, :parent => :daemontools do
-    desc "Runit service management.
-    This provider manages daemons running supervised by Runit.
-    It tries to detect the service directory, with by order of preference:
-     * /service
-     * /var/service
-     * /etc/service
-    The daemon directory should be placed in a directory that can be 
-    by default in:
-     * /etc/sv
-    or this can be overriden in the service resource parameters:
-    service {
-     \"myservice\":
-       provider => \"runit\", path => \"/path/to/daemons\";
-    }
-
-    This provider supports out of the box:
-     * start/stop
-     * enable/disable
-     * restart
-     * status"
-
-    commands :sv => "/usr/bin/sv"
-
-    class << self
-        # this is necessary to autodetect a valid resource
-        # default path, since there is no standard for such directory.
-        def defpath
-            unless defined?(@defpath) and @defpath
-                ["/etc/sv", "/var/lib/service"].each do |path|
-                    if FileTest.exist?(path)
-                        @defpath = path
-                        break
-                    end
-                end
-                raise "Could not find the daemon directory (tested [/var/lib/service,/etc])" unless @defpath
-            end
-            @defpath
-        end
-    end
-
-    # find the service dir on this node
-    def servicedir
-      unless defined?(@servicedir) and @servicedir
-        ["/service", "/etc/service","/var/service"].each do |path|
-            if FileTest.exist?(path)
-                @servicedir = path
-                break
-            end
-        end
-        raise "Could not find service directory" unless @servicedir
-      end
-      @servicedir
-    end
-
-    def restartcmd
-        [ command(:sv), "restart", self.service]
-    end
-
-    def status
-        begin
-            output = sv "status", self.daemon
-            return :running if output =~ /^run: /
-        rescue Puppet::ExecutionFailure => detail
-            unless detail.message =~ /(warning: |runsv not running$)/
-                raise Puppet::Error.new( "Could not get status for service %s: %s" % [ resource.ref, detail] )
-            end
-        end
-        return :stopped
-    end
-
-    # relay to the stopcmd
-    def stop
-        ucommand( :stop )
-    end
-
-    def stopcmd
-        [ command(:sv), "stop", self.service]
-    end
-
-    # disable by removing the symlink so that runit
-    # doesn't restart our service behind our back
-    # note that runit doesn't need to perform a stop
-    # before a disable
-    def disable
-        # unlink the daemon symlink to disable it
-        File.unlink(self.service) if FileTest.symlink?(self.service)
-    end
-end
-
diff --git a/lib/puppet/provider/service/smf.rb b/lib/puppet/provider/service/smf.rb
index ab1fe88..c74ce3f 100755
--- a/lib/puppet/provider/service/smf.rb
+++ b/lib/puppet/provider/service/smf.rb
@@ -7,8 +7,6 @@ Puppet::Type.type(:service).provide :smf, :parent => :base do
 
     defaultfor :operatingsystem => :solaris
 
-    confine :operatingsystem => :solaris
-
     commands :adm => "/usr/sbin/svcadm", :svcs => "/usr/bin/svcs"
 
     def enable
diff --git a/lib/puppet/provider/ssh_authorized_key/parsed.rb b/lib/puppet/provider/ssh_authorized_key/parsed.rb
deleted file mode 100644
index 5411a1f..0000000
--- a/lib/puppet/provider/ssh_authorized_key/parsed.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-require 'puppet/provider/parsedfile'
-
-Puppet::Type.type(:ssh_authorized_key).provide(:parsed,
-    :parent => Puppet::Provider::ParsedFile,
-    :filetype => :flat,
-    :default_target => ''
-) do
-    desc "Parse and generate authorized_keys files for SSH."
-
-    text_line :comment, :match => /^#/
-    text_line :blank, :match => /^\s+/
-
-    record_line :parsed,
-        :fields   => %w{options type key name},
-        :optional => %w{options},
-        :rts => /^\s+/,
-        :match    => /^(?:(.+) )?(ssh-dss|ssh-rsa) ([^ ]+)(?: (.+))?$/,
-        :post_parse => proc { |record|
-            if record[:options].nil?
-                record[:options] = [:absent]
-            else
-                record[:options] = record[:options].split(',')
-            end
-        },
-        :pre_gen => proc { |record|
-            if record[:options].include?(:absent)
-                record[:options] = ""
-            else
-                record[:options] = record[:options].join(',')
-            end
-        }
-
-    record_line :key_v1,
-        :fields   => %w{options bits exponent modulus name},
-        :optional => %w{options},
-        :rts      => /^\s+/,
-        :match    => /^(?:(.+) )?(\d+) (\d+) (\d+)(?: (.+))?$/
-
-    def prefetch
-        # This was done in the type class but path expansion was failing for
-        # not yet existing users, the only workaround I found was to move that
-        # in the provider.
-        if user = @resource.should(:user)
-            target = File.expand_path("~%s/.ssh/authorized_keys" % user)
-            @property_hash[:target] = target
-            @resource[:target] = target
-        end
-
-        super
-    end
-
-    def flush
-        # As path expansion had to be moved in the provider, we cannot generate new file
-        # resources and thus have to chown and chmod here. It smells hackish.
-        
-        # Create target's parent directory if nonexistant
-        if target = @property_hash[:target]
-            dir = File.dirname(@property_hash[:target])
-            if not File.exist? dir
-                Puppet.debug("Creating directory %s which did not exist" % dir)
-                Dir.mkdir(dir, 0700)
-            end
-        end
-
-        # Generate the file
-        super
-
-        # Ensure correct permissions
-        if target and user = @property_hash[:user]
-            File.chown(Puppet::Util.uid(user), nil, dir)
-            File.chown(Puppet::Util.uid(user), nil, @property_hash[:target])
-        end
-    end
-end
-
diff --git a/lib/puppet/provider/user/hpux.rb b/lib/puppet/provider/user/hpux.rb
deleted file mode 100644
index 672b77d..0000000
--- a/lib/puppet/provider/user/hpux.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-Puppet::Type.type(:user).provide :hpuxuseradd, :parent => :useradd do
-    desc "User management for hp-ux! Undocumented switch to special usermod because HP-UX regular usermod is TOO STUPID to change stuff while the user is logged in."
-
-    defaultfor :operatingsystem => "hp-ux"
-    confine :operatingsystem => "hp-ux"
-    
-    commands :modify => "/usr/sam/lbin/usermod.sam", :delete => "/usr/sam/lbin/userdel.sam", :add => "/usr/sbin/useradd"
-    options :comment, :method => :gecos
-    options :groups, :flag => "-G"
-    options :home, :flag => "-d", :method => :dir
-
-    verify :gid, "GID must be an integer" do |value|
-        value.is_a? Integer
-    end
-
-    verify :groups, "Groups must be comma-separated" do |value|
-        value !~ /\s/
-    end
-
-    has_features :manages_homedir, :allows_duplicates
-
-    def deletecmd
-	super.insert(1,"-F")
-    end
-
-    def modifycmd(param,value)
-	super.insert(1,"-F")
-    end
-
-end
diff --git a/lib/puppet/provider/user/ldap.rb b/lib/puppet/provider/user/ldap.rb
deleted file mode 100644
index 2e200a8..0000000
--- a/lib/puppet/provider/user/ldap.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-require 'puppet/provider/ldap'
-
-Puppet::Type.type(:user).provide :ldap, :parent => Puppet::Provider::Ldap do
-    desc "User management via ``ldap``.  This provider requires that you
-        have valid values for all of the ldap-related settings,
-        including ``ldapbase``.  You will also almost definitely need settings
-        for ``ldapuser`` and ``ldappassword``, so that your clients can write
-        to ldap.
-        
-        Note that this provider will automatically generate a UID for you if
-        you do not specify one, but it is a potentially expensive operation,
-        as it iterates across all existing users to pick the appropriate next
-        one."
-
-    confine :feature => :ldap, :false => (Puppet[:ldapuser] == "")
-
-    has_feature :manages_passwords
-
-    manages(:posixAccount, :person).at("ou=People").named_by(:uid).and.maps :name => :uid,
-        :password => :userPassword,
-        :comment => :cn,
-        :uid => :uidNumber,
-        :gid => :gidNumber,
-        :home => :homeDirectory,
-        :shell => :loginShell
-
-    # Use the last field of a space-separated array as
-    # the sn.  LDAP requires a surname, for some stupid reason.
-    manager.generates(:sn).from(:cn).with do |cn|
-        x = 1
-        cn[0].split(/\s+/)[-1]
-    end
-
-    # Find the next uid after the current largest uid.
-    provider = self
-    manager.generates(:uidNumber).with do 
-        largest = 500
-        if existing = provider.manager.search
-            existing.each do |hash|
-                next unless value = hash[:uid]
-                num = value[0].to_i
-                if num > largest
-                    largest = num
-                end
-            end
-        end
-        largest + 1
-    end
-
-    # Convert our gid to a group name, if necessary.
-    def gid=(value)
-        unless [Fixnum, Bignum].include?(value.class)
-            value = group2id(value)
-        end
-
-        @property_hash[:gid] = value
-    end
-
-    # Find all groups this user is a member of in ldap.
-    def groups
-        # We want to cache the current result, so we know if we
-        # have to remove old values.
-        unless @property_hash[:groups]
-            unless result = group_manager.search("memberUid=%s" % name)
-                return @property_hash[:groups] = :absent
-            end
-
-            return @property_hash[:groups] = result.collect { |r| r[:name] }.join(",")
-        end
-        return @property_hash[:groups]
-    end
-
-    # Manage the list of groups this user is a member of.
-    def groups=(values)
-        should = values.split(",")
-
-        if groups() == :absent
-            is = []
-        else
-            is = groups().split(",")
-        end
-
-        modes = {}
-        [is, should].flatten.uniq.each do |group|
-            # Skip it when they're in both
-            next if is.include?(group) and should.include?(group)
-
-            # We're adding a group.
-            modes[group] = :add and next unless is.include?(group)
-
-            # We're removing a group.
-            modes[group] = :remove and next unless should.include?(group)
-        end
-
-        modes.each do |group, form|
-            self.fail "Could not find ldap group %s" % group unless ldap_group = group_manager.find(group)
-
-            current = ldap_group[:members]
-
-            if form == :add
-                if current.is_a?(Array) and ! current.empty?
-                    new = current + [name]
-                else
-                    new = [name]
-                end
-            else
-                new = current - [name]
-                new = :absent if new.empty?
-            end
-
-            group_manager.update(group, {:ensure => :present, :members => current}, {:ensure => :present, :members => new})
-        end
-    end
-
-    # Convert a gropu name to an id.
-    def group2id(group)
-        Puppet::Type.type(:group).provider(:ldap).name2id(group)
-    end
-
-    private
-
-    def group_manager
-        Puppet::Type.type(:group).provider(:ldap).manager
-    end
-
-    def group_properties(values)
-        if values.empty? or values == :absent
-            {:ensure => :present}
-        else
-            {:ensure => :present, :members => values}
-        end
-    end
-end
diff --git a/lib/puppet/provider/user/user_role_add.rb b/lib/puppet/provider/user/user_role_add.rb
deleted file mode 100644
index 00fc24b..0000000
--- a/lib/puppet/provider/user/user_role_add.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-require 'puppet/util/user_attr'
-
-Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd do
-
-    desc "User management inherits ``useradd`` and adds logic to manage roles on Solaris using roleadd."
-
-    defaultfor :operatingsystem => :solaris
-
-    commands :add => "useradd", :delete => "userdel", :modify => "usermod", :role_add => "roleadd", :role_delete => "roledel", :role_modify => "rolemod"
-    options :home, :flag => "-d", :method => :dir
-    options :comment, :method => :gecos
-    options :groups, :flag => "-G"
-    options :roles, :flag => "-R"
-    options :auths, :flag => "-A"
-    options :profiles, :flag => "-P"
-
-    verify :gid, "GID must be an integer" do |value|
-        value.is_a? Integer
-    end
-
-    verify :groups, "Groups must be comma-separated" do |value|
-        value !~ /\s/
-    end
-
-    has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac
-
-    if Puppet.features.libshadow?
-        has_feature :manages_passwords
-    end
-
-    #must override this to hand the keyvalue pairs
-    def add_properties
-        cmd = []
-        Puppet::Type.type(:user).validproperties.each do |property|
-            next if property == :ensure
-            # the value needs to be quoted, mostly because -c might
-            # have spaces in it
-            if value = @resource.should(property) and value != ""
-                if property == :keys
-                    cmd += build_keys_cmd(value)
-                else
-                    cmd << flag(property) << value
-                end
-            end
-        end
-        cmd
-    end
-
-    def user_attributes
-        @user_attributes ||= UserAttr.get_attributes_by_name(@resource[:name])
-    end
-
-    def flush
-        @user_attributes = nil
-    end
-
-    def command(cmd)
-        if is_role? or (!exists? and @resource[:ensure] == :role)
-            cmd = ("role_" + cmd.to_s).intern
-        end
-        super(cmd)
-    end
-
-    def is_role?
-        user_attributes and user_attributes[:type] == "role"
-    end
-
-    def run(cmd, msg)
-        begin
-            execute(cmd)
-        rescue Puppet::ExecutionFailure => detail
-            raise Puppet::Error, "Could not %s %s %s: %s" %
-                [msg, @resource.class.name, @resource.name, detail]
-        end
-    end
-
-    def transition(type)
-        cmd = [command(:modify)]
-        cmd << "-K" << "type=#{type}"
-        cmd += add_properties
-        cmd << @resource[:name]
-    end
-
-    def create
-        if is_role?
-            run(transition("normal"), "transition role to")
-        else
-            run(addcmd, "create")
-        end
-    end
-
-    def destroy
-        run(deletecmd, "delete "+ (is_role? ? "role" : "user"))
-    end
-
-    def create_role
-        if exists? and !is_role?
-            run(transition("role"), "transition user to")
-        else
-            run(addcmd, "create role")
-        end
-    end
-
-    def roles
-        if user_attributes
-            user_attributes[:roles]
-        end
-    end
-
-    def auths
-        if user_attributes
-            user_attributes[:auths]
-        end
-    end
-
-    def profiles
-        if user_attributes
-            user_attributes[:profiles]
-        end
-    end
-
-    def project
-        if user_attributes
-            user_attributes[:project]
-        end
-    end
-
-    def managed_attributes
-        [:name, :type, :roles, :auths, :profiles, :project]
-    end
-
-    def remove_managed_attributes
-        managed = managed_attributes
-        user_attributes.select { |k,v| !managed.include?(k) }.inject({}) { |hash, array| hash[array[0]] = array[1]; hash }
-    end
-
-    def keys
-        if user_attributes
-            #we have to get rid of all the keys we are managing another way
-            remove_managed_attributes
-        end
-    end
-
-    def build_keys_cmd(keys_hash)
-        cmd = []
-        keys_hash.each do |k,v|
-            cmd << "-K" << "#{k}=#{v}"
-        end
-        cmd
-    end
-
-    def keys=(keys_hash)
-        run([command(:modify)] + build_keys_cmd(keys_hash) << @resource[:name], "modify attribute key pairs")
-    end
-end
-
diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb
index 6996dd6..e64601e 100644
--- a/lib/puppet/provider/user/useradd.rb
+++ b/lib/puppet/provider/user/useradd.rb
@@ -23,23 +23,9 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
         has_feature :manages_passwords
     end
 
-    def check_allow_dup
-        @resource.allowdupe? ? ["-o"] : []
-    end
-
-    def check_manage_home
-        cmd = []
-        if @resource.managehome?
-            cmd << "-m"
-        elsif %w{Fedora RedHat}.include?(Facter.value("operatingsystem"))
-            cmd << "-M"
-        end
-        cmd
-    end
-
-    def add_properties
-        cmd = []
-        Puppet::Type.type(:user).validproperties.each do |property|
+    def addcmd
+        cmd = [command(:add)]
+        @resource.class.validproperties.each do |property|
             next if property == :ensure
             # the value needs to be quoted, mostly because -c might
             # have spaces in it
@@ -47,15 +33,20 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
                 cmd << flag(property) << value
             end
         end
-        cmd
-    end
 
-    def addcmd
-        cmd = [command(:add)]
-        cmd += add_properties
-        cmd += check_allow_dup
-        cmd += check_manage_home
+        if @resource.allowdupe?
+            cmd << "-o"
+        end
+
+        if @resource.managehome?
+            cmd << "-m"
+        elsif %w{Fedora RedHat}.include?(Facter.value("operatingsystem"))
+            cmd << "-M"
+        end
+
         cmd << @resource[:name]
+
+        cmd
     end
 
     # Retrieve the password using the Shadow Password library
diff --git a/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb b/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb
index d1035b0..71ee6ae 100644
--- a/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb
+++ b/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb
@@ -1,17 +1,17 @@
 class AddCreatedAtToAllTables < ActiveRecord::Migration
-    def self.up
-        ActiveRecord::Base.connection.tables.each do |t|
-            unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
-                add_column t.to_s, :created_at, :datetime 
-            end    
-        end 
-    end
+  def self.up
+    ActiveRecord::Base.connection.tables.each do |t|
+      unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
+        add_column t.to_s, :created_at, :datetime 
+      end  
+    end 
+  end
 
-    def self.down
-        ActiveRecord::Base.connection.tables.each do |t|
-            unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
-                remove_column t.to_s, :created_at
-            end    
-        end    
-    end
+  def self.down
+    ActiveRecord::Base.connection.tables.each do |t|
+      unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
+        remove_column t.to_s, :created_at
+      end  
+    end  
+  end
 end
diff --git a/lib/puppet/rails/database/002_remove_duplicated_index_on_all_tables.rb b/lib/puppet/rails/database/002_remove_duplicated_index_on_all_tables.rb
deleted file mode 100644
index 3873a13..0000000
--- a/lib/puppet/rails/database/002_remove_duplicated_index_on_all_tables.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-class RemoveDuplicatedIndexOnAllTables < ActiveRecord::Migration
-    def self.up
-        ActiveRecord::Base.connection.tables.each do |t|
-            if ActiveRecord::Base.connection.indexes(t).collect {|c| c.columns}.include?("id")
-                remove_index t.to_s, :id
-            end
-        end 
-    end
-
-    def self.down
-        ActiveRecord::Base.connection.tables.each do |t|
-            unless ActiveRecord::Base.connection.indexes(t).collect {|c| c.columns}.include?("id")
-                add_index t.to_s, :id, :integer => true
-            end
-        end    
-    end
-end
diff --git a/lib/puppet/rails/database/schema.rb b/lib/puppet/rails/database/schema.rb
index f3ad2c1..5365ce2 100644
--- a/lib/puppet/rails/database/schema.rb
+++ b/lib/puppet/rails/database/schema.rb
@@ -14,8 +14,8 @@ class Puppet::Rails::Schema
                     t.column :exported, :boolean
                     t.column :line, :integer
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end
+                add_index :resources, :id, :integer => true
                 add_index :resources, :host_id, :integer => true
                 add_index :resources, :source_file_id, :integer => true
 
@@ -31,23 +31,22 @@ class Puppet::Rails::Schema
                     t.column :filename, :string
                     t.column :path, :string
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end
+                add_index :source_files, :id, :integer => true
                 add_index :source_files, :filename
 
                 create_table :resource_tags do |t|
                     t.column :resource_id, :integer
                     t.column :puppet_tag_id, :integer
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end
+                add_index :resource_tags, :id, :integer => true
                 add_index :resource_tags, :resource_id, :integer => true
                 add_index :resource_tags, :puppet_tag_id, :integer => true
 
                 create_table :puppet_tags do |t| 
                     t.column :name, :string
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end
                 add_index :puppet_tags, :id, :integer => true
 
@@ -60,16 +59,16 @@ class Puppet::Rails::Schema
                     #Use updated_at to automatically add timestamp on save.
                     t.column :updated_at, :datetime
                     t.column :source_file_id, :integer
-                    t.column :created_at, :datetime
                 end
+                add_index :hosts, :id, :integer => true
                 add_index :hosts, :source_file_id, :integer => true
                 add_index :hosts, :name
 
                 create_table :fact_names do |t| 
                     t.column :name, :string, :null => false
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end
+                add_index :fact_names, :id, :integer => true
                 add_index :fact_names, :name
 
                 create_table :fact_values do |t| 
@@ -77,8 +76,8 @@ class Puppet::Rails::Schema
                     t.column :fact_name_id, :integer, :null => false
                     t.column :host_id, :integer, :null => false
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end 
+                add_index :fact_values, :id, :integer => true
                 add_index :fact_values, :fact_name_id, :integer => true
                 add_index :fact_values, :host_id, :integer => true
 
@@ -88,16 +87,16 @@ class Puppet::Rails::Schema
                     t.column :line, :integer
                     t.column :resource_id, :integer
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end
+                add_index :param_values, :id, :integer => true
                 add_index :param_values, :param_name_id, :integer => true
                 add_index :param_values, :resource_id, :integer => true
          
                 create_table :param_names do |t| 
                     t.column :name, :string, :null => false
                     t.column :updated_at, :datetime
-                    t.column :created_at, :datetime
                 end
+                add_index :param_names, :id, :integer => true
                 add_index :param_names, :name
             end 
         end
diff --git a/lib/puppet/rails/resource.rb b/lib/puppet/rails/resource.rb
index 255b0e7..785c634 100644
--- a/lib/puppet/rails/resource.rb
+++ b/lib/puppet/rails/resource.rb
@@ -6,12 +6,12 @@ require 'puppet/util/rails/collection_merger'
 class Puppet::Rails::Resource < ActiveRecord::Base
     include Puppet::Util::CollectionMerger
 
-    has_many :param_values, :dependent => :destroy, :class_name => "Puppet::Rails::ParamValue"
-    has_many :param_names, :through => :param_values, :class_name => "Puppet::Rails::ParamName"
-
-    has_many :resource_tags, :dependent => :destroy, :class_name => "Puppet::Rails::ResourceTag"
-    has_many :puppet_tags, :through => :resource_tags, :class_name => "Puppet::Rails::PuppetTag"
+    has_many :param_values, :dependent => :destroy
+    has_many :param_names, :through => :param_values
 
+    has_many :resource_tags, :dependent => :destroy
+    has_many :puppet_tags, :through => :resource_tags
+    
     belongs_to :source_file
     belongs_to :host
 
@@ -82,7 +82,7 @@ class Puppet::Rails::Resource < ActiveRecord::Base
     end
 
     def ref
-        "%s[%s]" % [self[:restype].split("::").collect { |s| s.capitalize }.join("::"), self[:title]]
+        "%s[%s]" % [self[:restype].capitalize, self[:title]]
     end
 
     # Convert our object to a resource.  Do not retain whether the object
@@ -98,7 +98,6 @@ class Puppet::Rails::Resource < ActiveRecord::Base
         hash.delete("host_id")
         hash.delete("updated_at")
         hash.delete("source_file_id")
-        hash.delete("created_at")
         hash.delete("id")
         hash.each do |p, v|
             hash.delete(p) if v.nil?
diff --git a/lib/puppet/reference/configuration.rb b/lib/puppet/reference/configuration.rb
index 8e82c8a..2c424e0 100644
--- a/lib/puppet/reference/configuration.rb
+++ b/lib/puppet/reference/configuration.rb
@@ -49,6 +49,10 @@ On The Command-Line
 +++++++++++++++++++
 Every Puppet executable (with the exception of ``puppetdoc``) accepts all of
 the parameters below, but not all of the arguments make sense for every executable.
+Each parameter has a section listed with it in parentheses; often, that section
+will map to an executable (e.g., ``puppetd``), in which case it probably only
+makes sense for that one executable.  If ``main`` is listed as the section,
+it is most likely an option that is valid for everyone.
 
 I have tried to be as thorough as possible in the descriptions of the
 arguments, so it should be obvious whether an argument is appropriate or not.
@@ -117,6 +121,9 @@ Note that this invocation will replace the contents of any pre-existing
 `puppet.conf` file, so make a backup of your present config if it contains
 valuable information.
 
+All parameters will be under a single section heading matching the name of
+the process used to generate the configuraiton ('puppetd', in this case).
+  
 Like the `--genconfig` argument, the executables also accept a `--genmanifest`
 argument, which will generate a manifest that can be used to manage all of 
 Puppet's directories and files and prints it to standard output.  This can
diff --git a/lib/puppet/reference/providers.rb b/lib/puppet/reference/providers.rb
index 8fd2dba..da815dd 100644
--- a/lib/puppet/reference/providers.rb
+++ b/lib/puppet/reference/providers.rb
@@ -63,20 +63,14 @@ providers = Puppet::Util::Reference.newreference :providers, :title => "Provider
                     case test
                     when :exists:
                         details += "  - Missing files %s\n" % values.join(", ")
-                    when :variable:
+                    when :facter:
                         values.each do |name, facts|
-                            if Puppet.settings.valid?(name)
-                                details += "  - Setting %s (currently %s) not in list %s\n" % [name, Puppet.settings.value(name).inspect, facts.join(", ")]
-                            else
-                                details += "  - Fact %s (currently %s) not in list %s\n" % [name, Facter.value(name).inspect, facts.join(", ")]
-                            end
+                            details += "  - Fact %s (currently %s) not in list %s\n" % [name, Facter.value(name).inspect, facts.join(", ")]
                         end
                     when :true:
                         details += "  - Got %s true tests that should have been false\n" % values
                     when :false:
                         details += "  - Got %s false tests that should have been true\n" % values
-                    when :feature:
-                        details += "  - Missing features %s\n" % values.collect { |f| f.to_s }.join(",")
                     end
                 end
                 notes << details
diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb
index 5889750..03d8a5b 100644
--- a/lib/puppet/reports/rrdgraph.rb
+++ b/lib/puppet/reports/rrdgraph.rb
@@ -90,9 +90,8 @@ Puppet::Reports.register_report(:rrdgraph) do
             of.puts "<html><head><title>Report graphs for %s</title></head><body>" %
                 host
             files.each do |file|
-                of.puts "<a href='%s'>%s</a><br/>" %
-                    [File.basename(file),
-                     File.basename(file).sub(".html",'').capitalize]
+                of.puts "<a href='#{File.basename(file)}'>%s</a><br/>" %
+                    File.basename(file).sub(".html",'').capitalize
             end
             of.puts "</body></html>"
         end
diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb
index 2a16a32..7386318 100644
--- a/lib/puppet/sslcertificates/ca.rb
+++ b/lib/puppet/sslcertificates/ca.rb
@@ -97,7 +97,7 @@ class Puppet::SSLCertificates::CA
         if @config[:capass] and File.readable?(@config[:capass])
             return File.read(@config[:capass])
         else
-            raise Puppet::Error, "Could not decrypt CA key with password: %s" % detail
+            raise Puppet::Error, "Could not read CA passfile %s" % @config[:capass]
         end
     end
 
@@ -379,14 +379,9 @@ class Puppet::SSLCertificates::CA
     def sign_with_key(signable, digest = OpenSSL::Digest::SHA1.new)
         cakey = nil
         if @config[:password]
-            begin
-                cakey = OpenSSL::PKey::RSA.new(
-                    File.read(@config[:cakey]), @config[:password]
-                )
-            rescue
-                raise Puppet::Error,
-                    "Decrypt of CA private key with password stored in @config[:capass] not possible"
-            end
+            cakey = OpenSSL::PKey::RSA.new(
+                File.read(@config[:cakey]), @config[:password]
+            )
         else
             cakey = OpenSSL::PKey::RSA.new(
                 File.read(@config[:cakey])
diff --git a/lib/puppet/sslcertificates/inventory.rb b/lib/puppet/sslcertificates/inventory.rb
index 295c416..da959aa 100644
--- a/lib/puppet/sslcertificates/inventory.rb
+++ b/lib/puppet/sslcertificates/inventory.rb
@@ -7,9 +7,8 @@ module Puppet::SSLCertificates
         # If no inventory exists yet, build an inventory and list all the 
         # certificates that have been signed so far
         def self.add(cert)
-            inited = false
-            if FileTest.exists?(Puppet[:cert_inventory])
-                inited = true
+            unless FileTest.exists?(Puppet[:cert_inventory])
+                inited = false
             end
 
             Puppet.settings.write(:cert_inventory, "a") do |f|
diff --git a/lib/puppet/sslcertificates/support.rb b/lib/puppet/sslcertificates/support.rb
index 5ca0672..1d692c9 100644
--- a/lib/puppet/sslcertificates/support.rb
+++ b/lib/puppet/sslcertificates/support.rb
@@ -28,8 +28,7 @@ module Puppet::SSLCertificates::Support
 
         # Define the reading method.
         define_method(reader) do
-            return nil unless FileTest.exists?(Puppet[param]) or rename_files_with_uppercase(Puppet[param])
-
+            return nil unless FileTest.exists?(Puppet[param])
             begin
                 instance_variable_set(var, klass.new(File.read(Puppet[param])))
             rescue => detail
@@ -122,31 +121,5 @@ module Puppet::SSLCertificates::Support
         end
         return retrieved
     end
-
-    # A hack method to deal with files that exist with a different case.
-    # Just renames it; doesn't read it in or anything.
-    def rename_files_with_uppercase(file)
-        dir = File.dirname(file)
-        short = File.basename(file)
-
-        # If the dir isn't present, we clearly don't have the file.
-        #return nil unless FileTest.directory?(dir)
-
-        raise ArgumentError, "Tried to fix SSL files to a file containing uppercase" unless short.downcase == short
-
-        return false unless File.directory?(dir)
-
-        real_file = Dir.entries(dir).reject { |f| f =~ /^\./ }.find do |other|
-            other.downcase == short
-        end
-
-        return nil unless real_file
-
-        full_file = File.join(dir, real_file)
-
-        Puppet.notice "Fixing case in %s; renaming to %s" % [full_file, file]
-        File.rename(full_file, file)
-
-        return true
-    end
 end
+
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index f3defb7..14b2037 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -2,12 +2,10 @@
 # and performs them
 
 require 'puppet'
+require 'puppet/propertychange'
 
 module Puppet
 class Transaction
-    require 'puppet/transaction/change'
-    require 'puppet/transaction/event'
-
     attr_accessor :component, :catalog, :ignoreschedules
     attr_accessor :sorted_resources, :configurator
 
@@ -98,7 +96,7 @@ class Transaction
                 # Create an edge with this resource as both the source and
                 # target.  The triggering method treats these specially for
                 # logging.
-                events = resourceevents.collect { |e| e.name }
+                events = resourceevents.collect { |e| e.event }
                 set_trigger(Puppet::Relationship.new(resource, resource, :callback => :refresh, :event => events))
             end
         end
@@ -111,6 +109,7 @@ class Transaction
         changes.collect { |change|
             @changes << change
             @count += 1
+            change.transaction = self
             events = nil
             begin
                 # use an array, so that changes can return more than one
@@ -279,7 +278,7 @@ class Transaction
             # of course, bad.
             edge = orig_edge.class.new(orig_edge.source, orig_edge.target)
             label = orig_edge.label.dup
-            label[:event] = events.collect { |e| e.name }
+            label[:event] = events.collect { |e| e.event }
             edge.label = label
             set_trigger(edge)
         end
@@ -500,12 +499,10 @@ class Transaction
     
     # Prepare to evaluate the resources in a transaction.
     def prepare
+        prefetch()
+    
         # Now add any dynamically generated resources
         generate()
-
-        # Then prefetch.  It's important that we generate and then prefetch,
-        # so that any generated resources also get prefetched.
-        prefetch()
         
         # This will throw an error if there are cycles in the graph.
         @sorted_resources = relationship_graph.topsort
@@ -681,7 +678,11 @@ class Transaction
                     [callback, subs.length]
 
                 # And then add an event for it.
-                return [Puppet::Transaction::Event.new(:noop, resource)]
+                return [Puppet::Event.new(
+                    :event => :noop,
+                    :transaction => self,
+                    :source => resource
+                )]
             end
 
             if subs.length == 1 and subs[0].source == resource
@@ -709,7 +710,11 @@ class Transaction
             end
 
             # And then add an event for it.
-            trigged << Puppet::Transaction::Event.new(:triggered, resource)
+            trigged << Puppet::Event.new(
+                :event => :triggered,
+                :transaction => self,
+                :source => resource
+            )
 
             triggered(resource, callback)
         end
diff --git a/lib/puppet/transaction/change.rb b/lib/puppet/transaction/change.rb
deleted file mode 100644
index e05c259..0000000
--- a/lib/puppet/transaction/change.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-require 'puppet/transaction'
-require 'puppet/transaction/event'
-
-# Handle all of the work around performing an actual change,
-# including calling 'sync' on the properties and producing events.
-class Puppet::Transaction::Change
-    attr_accessor :is, :should, :path, :property, :changed, :proxy
-    
-    # Switch the goals of the property, thus running the change in reverse.
-    def backward
-        @is, @should = @should, @is
-        @property.should = @should
-
-        @property.info "Reversing %s" % self
-        return self.go
-    end
-    
-    def changed?
-        self.changed
-    end
-
-    # Create our event object.
-    def event(name)
-        # default to a simple event type
-        unless name.is_a?(Symbol)
-            @property.warning("Property '%s' returned invalid event '%s'; resetting to default" %
-                [@property.class, name])
-
-            name = @property.event(should)
-        end
-        
-        Puppet::Transaction::Event.new(name, self.resource)
-    end
-
-    def initialize(property, currentvalue)
-        @property = property
-        @path = [property.path,"change"].flatten
-        @is = currentvalue
-
-        @should = property.should
-
-        @changed = false
-    end
-
-    # Perform the actual change.  This method can go either forward or
-    # backward, and produces an event.
-    def go
-        if self.noop?
-            @property.log "is %s, should be %s (noop)" % [property.is_to_s(@is), property.should_to_s(@should)]
-            return [event(:noop)]
-        end
-
-        # The transaction catches any exceptions here.
-        events = @property.sync
-        if events.nil?
-            return nil
-        end
-
-        if events.is_a?(Array)
-            if events.empty?
-                return nil
-            end
-        else
-            events = [events]
-        end
-        
-        return events.collect { |name|
-            @report = @property.log(@property.change_to_s(@is, @should))
-            event(name)
-        }
-    end
-
-    def forward
-        return self.go
-    end
-    
-    # Is our property noop?  This is used for generating special events.
-    def noop?
-        return @property.noop
-    end
-    
-    # The resource that generated this change.  This is used for handling events,
-    # and the proxy resource is used for generated resources, since we can't
-    # send an event to a resource we don't have a direct relationship.  If we
-    # have a proxy resource, then the events will be considered to be from
-    # that resource, rather than us, so the graph resolution will still work.
-    def resource
-        self.proxy || @property.resource
-    end
-
-    def to_s
-        return "change %s" % @property.change_to_s(@is, @should)
-    end
-end
diff --git a/lib/puppet/transaction/event.rb b/lib/puppet/transaction/event.rb
deleted file mode 100644
index f1a48b3..0000000
--- a/lib/puppet/transaction/event.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'puppet'
-require 'puppet/util/methodhelper'
-require 'puppet/util/errors'
-
-# events are transient packets of information; they result in one or more (or none)
-# subscriptions getting triggered, and then they get cleared
-# eventually, these will be passed on to some central event system
-class Puppet::Transaction::Event
-    include Puppet::Util::MethodHelper
-    include Puppet::Util::Errors
-    
-    attr_reader :name, :source
-
-    def initialize(name, source)
-        @name, @source = name, source
-    end
-
-    def to_s
-        source.to_s + " -> " + name.to_s
-    end
-end
diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb
index 89da7ed..bd62ebb 100644
--- a/lib/puppet/transaction/report.rb
+++ b/lib/puppet/transaction/report.rb
@@ -25,7 +25,13 @@ class Puppet::Transaction::Report
             hash[key] = []
         end
 
-        @host = Puppet[:certname]
+        domain = Facter.value("domain")
+        hostname = Facter.value("hostname")
+        if !domain || domain.empty? then
+            @host = hostname
+        else
+            @host = [hostname, domain].join(".")
+        end
     end
 
     def name
diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb
index d203b59..3ad084b 100644
--- a/lib/puppet/transportable.rb
+++ b/lib/puppet/transportable.rb
@@ -65,16 +65,13 @@ module Puppet
         end
 
         def to_manifest
-            "%s { '%s':\n%s\n}" % 
-                [self.type.to_s, self.name,
-                 @params.collect { |p, v|
-                     if v.is_a? Array
-                         "    #{p} => [\'#{v.join("','")}\']"
-                     else
-                         "    #{p} => \'#{v}\'"
-                     end
-                 }.join(",\n")
-                ]
+            "#{self.type.to_s} { \'#{self.name}\':\n%s\n}" % @params.collect { |p, v|
+                if v.is_a? Array
+                    "    #{p} => [\'#{v.join("','")}\']"
+                else
+                    "    #{p} => \'#{v}\'"
+                end
+            }.join(",\n")
         end
 
         def to_yaml_properties
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index 7e86549..f8949ec 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -1,5 +1,6 @@
 require 'puppet'
 require 'puppet/util/log'
+require 'puppet/event'
 require 'puppet/util/metric'
 require 'puppet/property'
 require 'puppet/parameter'
@@ -20,2116 +21,20 @@ class Type
     include Puppet::Util::LogPaths
     include Puppet::Util::Logging
 
-    ###############################
-    # Code related to resource type attributes.
-    class << self
-        include Puppet::Util::ClassGen
-        include Puppet::Util::Warnings
-        attr_reader :properties
-    end
-
-    def self.states
-        warnonce "The states method is deprecated; use properties"
-        properties()
-    end
-
-    # All parameters, in the appropriate order.  The namevar comes first,
-    # then the properties, then the params and metaparams in the order they
-    # were specified in the files.
-    def self.allattrs
-        # now get all of the arguments, in a specific order
-        # Cache this, since it gets called so many times
-        namevar = self.namevar
-
-        order = [namevar]
-        if self.parameters.include?(:provider)
-            order << :provider
-        end
-        order << [self.properties.collect { |property| property.name },
-            self.parameters - [:provider],
-            self.metaparams].flatten.reject { |param|
-                # we don't want our namevar in there multiple times
-                param == namevar
-        }
-
-        order.flatten!
-
-        return order
-    end
-
-    # Retrieve an attribute alias, if there is one.
-    def self.attr_alias(param)
-        @attr_aliases[symbolize(param)]
-    end
-
-    # Create an alias to an existing attribute.  This will cause the aliased
-    # attribute to be valid when setting and retrieving values on the instance.
-    def self.set_attr_alias(hash)
-        hash.each do |new, old|
-            @attr_aliases[symbolize(new)] = symbolize(old)
-        end
-    end
-
-    # Find the class associated with any given attribute.
-    def self.attrclass(name)
-        @attrclasses ||= {}
-
-        # We cache the value, since this method gets called such a huge number
-        # of times (as in, hundreds of thousands in a given run).
-        unless @attrclasses.include?(name)
-            @attrclasses[name] = case self.attrtype(name)
-            when :property: @validproperties[name]
-            when :meta: @@metaparamhash[name]
-            when :param: @paramhash[name]
-            end
-        end
-        @attrclasses[name]
-    end
-
-    # What type of parameter are we dealing with? Cache the results, because
-    # this method gets called so many times.
-    def self.attrtype(attr)
-        @attrtypes ||= {}
-        unless @attrtypes.include?(attr)
-            @attrtypes[attr] = case
-                when @validproperties.include?(attr): :property
-                when @paramhash.include?(attr): :param
-                when @@metaparamhash.include?(attr): :meta
-                else
-                    raise Puppet::DevError,
-                        "Invalid attribute '%s' for class '%s'" %
-                        [attr, self.name]
-                end
-        end
-
-        @attrtypes[attr]
-    end
-
-    # Copy an existing class parameter.  This allows other types to avoid
-    # duplicating a parameter definition, and is mostly used by subclasses
-    # of the File class.
-    def self.copyparam(klass, name)
-        param = klass.attrclass(name)
-
-        unless param
-            raise Puppet::DevError, "Class %s has no param %s" % [klass, name]
-        end
-        @parameters << param
-        @parameters.each { |p| @paramhash[name] = p }
-
-        if param.isnamevar?
-            @namevar = param.name
-        end
-    end
-
-    # A similar function but one that yields the class and type.
-    # This is mainly so that setdefaults doesn't call quite so many functions.
-    def self.eachattr(*ary)
-        if ary.empty?
-            ary = nil
-        end
-
-        # We have to do this in a specific order, so that defaults are
-        # created in that order (e.g., providers should be set up before
-        # anything else).
-        allattrs.each do |name|
-            next unless ary.nil? or ary.include?(name)
-            if obj = @properties.find { |p| p.name == name }
-                yield obj, :property
-            elsif obj = @parameters.find { |p| p.name == name }
-                yield obj, :param
-            elsif obj = @@metaparams.find { |p| p.name == name }
-                yield obj, :meta
-            else
-                raise Puppet::DevError, "Could not find parameter %s" % name
-            end
-        end
-    end
-
-    def self.eachmetaparam
-        @@metaparams.each { |p| yield p.name }
-    end
-
-    # Create the 'ensure' class.  This is a separate method so other types
-    # can easily call it and create their own 'ensure' values.
-    def self.ensurable(&block)
-        if block_given?
-            self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block)
-        else
-            self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do
-                self.defaultvalues
-            end
-        end
-    end
-
-    # Should we add the 'ensure' property to this class?
-    def self.ensurable?
-        # If the class has all three of these methods defined, then it's
-        # ensurable.
-        ens = [:exists?, :create, :destroy].inject { |set, method|
-            set &&= self.public_method_defined?(method)
-        }
-
-        return ens
-    end
-    
-    # Deal with any options passed into parameters.
-    def self.handle_param_options(name, options)
-        # If it's a boolean parameter, create a method to test the value easily
-        if options[:boolean]
-            define_method(name.to_s + "?") do
-                val = self[name]
-                if val == :true or val == true
-                    return true
-                end
-            end
-        end
-        
-        # If this param handles relationships, store that information
-    end
-
-    # Is the parameter in question a meta-parameter?
-    def self.metaparam?(param)
-        @@metaparamhash.include?(symbolize(param))
-    end
-
-    # Find the metaparameter class associated with a given metaparameter name.
-    def self.metaparamclass(name)
-        @@metaparamhash[symbolize(name)]
-    end
-
-    def self.metaparams
-        @@metaparams.collect { |param| param.name }
-    end
-
-    def self.metaparamdoc(metaparam)
-        @@metaparamhash[metaparam].doc
-    end
-
-    # Create a new metaparam.  Requires a block and a name, stores it in the
-    # @parameters array, and does some basic checking on it.
-    def self.newmetaparam(name, options = {}, &block)
-        @@metaparams ||= []
-        @@metaparamhash ||= {}
-        name = symbolize(name)
-
-        param = genclass(name,
-            :parent => options[:parent] || Puppet::Parameter,
-            :prefix => "MetaParam",
-            :hash => @@metaparamhash,
-            :array => @@metaparams,
-            :attributes => options[:attributes],
-            &block
-        )
-
-        # Grr.
-        if options[:required_features]
-            param.required_features = options[:required_features]
-        end
-        
-        handle_param_options(name, options)
-
-        param.metaparam = true
-
-        return param
-    end
-
-    # Find the namevar
-    def self.namevar
-        unless defined? @namevar
-            params = @parameters.find_all { |param|
-                param.isnamevar? or param.name == :name
-            }
-
-            if params.length > 1
-                raise Puppet::DevError, "Found multiple namevars for %s" % self.name
-            elsif params.length == 1
-                @namevar = params[0].name
-            else
-                raise Puppet::DevError, "No namevar for %s" % self.name
-            end
-        end
-        @namevar
-    end
-
-    # Create a new parameter.  Requires a block and a name, stores it in the
-    # @parameters array, and does some basic checking on it.
-    def self.newparam(name, options = {}, &block)
-        options[:attributes] ||= {}
-        param = genclass(name,
-            :parent => options[:parent] || Puppet::Parameter,
-            :attributes => options[:attributes],
-            :block => block,
-            :prefix => "Parameter",
-            :array => @parameters,
-            :hash => @paramhash
-        )
-        
-        handle_param_options(name, options)
-
-        # Grr.
-        if options[:required_features]
-            param.required_features = options[:required_features]
-        end
-
-        param.isnamevar if options[:namevar]
-
-        # These might be enabled later.
-#        define_method(name) do
-#            @parameters[name].value
-#        end
-#
-#        define_method(name.to_s + "=") do |value|
-#            newparam(param, value)
-#        end
-
-        if param.isnamevar?
-            @namevar = param.name
-        end
-
-        return param
-    end
-
-    def self.newstate(name, options = {}, &block)
-        Puppet.warning "newstate() has been deprecrated; use newproperty(%s)" %
-            name
-        newproperty(name, options, &block)
-    end
-
-    # Create a new property. The first parameter must be the name of the property;
-    # this is how users will refer to the property when creating new instances.
-    # The second parameter is a hash of options; the options are:
-    # * <tt>:parent</tt>: The parent class for the property.  Defaults to Puppet::Property.
-    # * <tt>:retrieve</tt>: The method to call on the provider or @parent object (if
-    #   the provider is not set) to retrieve the current value.
-    def self.newproperty(name, options = {}, &block)
-        name = symbolize(name)
-
-        # This is here for types that might still have the old method of defining
-        # a parent class.
-        unless options.is_a? Hash
-            raise Puppet::DevError,
-                "Options must be a hash, not %s" % options.inspect
-        end
-
-        if @validproperties.include?(name) 
-            raise Puppet::DevError, "Class %s already has a property named %s" %
-                [self.name, name]
-        end
-
-        if parent = options[:parent]
-            options.delete(:parent)
-        else
-            parent = Puppet::Property
-        end
-
-        # We have to create our own, new block here because we want to define
-        # an initial :retrieve method, if told to, and then eval the passed
-        # block if available.
-        prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do
-            # If they've passed a retrieve method, then override the retrieve
-            # method on the class.
-            if options[:retrieve]
-                define_method(:retrieve) do
-                    provider.send(options[:retrieve])
-                end
-            end
-
-            if block
-                class_eval(&block)
-            end
-        end
-
-        # If it's the 'ensure' property, always put it first.
-        if name == :ensure
-            @properties.unshift prop
-        else
-            @properties << prop
-        end
-
-#        define_method(name) do
-#            @parameters[name].should
-#        end
-#
-#        define_method(name.to_s + "=") do |value|
-#            newproperty(name, :should => value)
-#        end
-
-        return prop
-    end
-
-    def self.paramdoc(param)
-        @paramhash[param].doc
-    end
-
-    # Return the parameter names
-    def self.parameters
-        return [] unless defined? @parameters
-        @parameters.collect { |klass| klass.name }
-    end
-
-    # Find the parameter class associated with a given parameter name.
-    def self.paramclass(name)
-        @paramhash[name]
-    end
-
-    # Return the property class associated with a name
-    def self.propertybyname(name)
-        @validproperties[name]
-    end
-
-    def self.validattr?(name)
-        name = symbolize(name)
-        return true if name == :name
-        @validattrs ||= {}
-
-        unless @validattrs.include?(name)
-            if self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)
-                @validattrs[name] = true
-            else
-                @validattrs[name] = false
-            end
-        end
-
-        @validattrs[name]
-    end
-
-    # does the name reflect a valid property?
-    def self.validproperty?(name)
-        name = symbolize(name)
-        if @validproperties.include?(name)
-            return @validproperties[name]
-        else
-            return false
-        end
-    end
-
-    # Return the list of validproperties
-    def self.validproperties
-        return {} unless defined? @parameters
-
-        return @validproperties.keys
-    end
-
-    # does the name reflect a valid parameter?
-    def self.validparameter?(name)
-        unless defined? @parameters
-            raise Puppet::DevError, "Class %s has not defined parameters" % self
-        end
-        if @paramhash.include?(name) or @@metaparamhash.include?(name)
-            return true
-        else
-            return false
-        end
-    end
-
-    # fix any namevar => param translations
-    def argclean(oldhash)
-        # This duplication is here because it might be a transobject.
-        hash = oldhash.dup.to_hash
-
-        if hash.include?(:resource)
-            hash.delete(:resource)
-        end
-        namevar = self.class.namevar
-
-        # Do a simple translation for those cases where they've passed :name
-        # but that's not our namevar
-        if hash.include? :name and namevar != :name
-            if hash.include? namevar
-                raise ArgumentError, "Cannot provide both name and %s" % namevar
-            end
-            hash[namevar] = hash[:name]
-            hash.delete(:name)
-        end
-
-        # Make sure we have a name, one way or another
-        unless hash.include? namevar
-            if defined? @title and @title
-                hash[namevar] = @title
-            else
-                raise Puppet::Error, "Was not passed a namevar or title"
-            end
-        end
-
-        return hash
-    end
-
-    # Return either the attribute alias or the attribute.
-    def attr_alias(name)
-        name = symbolize(name)
-        if synonym = self.class.attr_alias(name)
-            return synonym
-        else
-            return name
-        end
-    end
-    
-    # Are we deleting this resource?
-    def deleting?
-        obj = @parameters[:ensure] and obj.should == :absent
-    end
-
-    # Create a new property if it is valid but doesn't exist
-    # Returns: true if a new parameter was added, false otherwise
-    def add_property_parameter(prop_name)
-        if self.class.validproperty?(prop_name) && !@parameters[prop_name]
-            self.newattr(prop_name)
-            return true
-        end
-        return false
-    end
-    
-    # abstract accessing parameters and properties, and normalize
-    # access to always be symbols, not strings
-    # This returns a value, not an object.  It returns the 'is'
-    # value, but you can also specifically return 'is' and 'should'
-    # values using 'object.is(:property)' or 'object.should(:property)'.
-    def [](name)
-        name = attr_alias(name)
-
-        unless self.class.validattr?(name)
-            raise TypeError.new("Invalid parameter %s(%s)" % [name, name.inspect])
-        end
-
-        if name == :name
-            name = self.class.namevar
-        end
-
-        if obj = @parameters[name]
-            # Note that if this is a property, then the value is the "should" value,
-            # not the current value.
-            obj.value
-        else
-            return nil
-        end
-    end
-
-    # Abstract setting parameters and properties, and normalize
-    # access to always be symbols, not strings.  This sets the 'should'
-    # value on properties, and otherwise just sets the appropriate parameter.
-    def []=(name,value)
-        name = attr_alias(name)
-
-        unless self.class.validattr?(name)
-            raise TypeError.new("Invalid parameter %s" % [name])
-        end
-
-        if name == :name
-            name = self.class.namevar
-        end
-        if value.nil?
-            raise Puppet::Error.new("Got nil value for %s" % name)
-        end
-
-        if obj = @parameters[name]
-            obj.value = value
-            return nil
-        else
-            self.newattr(name, :value => value)
-        end
-
-        nil
-    end
-
-    # remove a property from the object; useful in testing or in cleanup
-    # when an error has been encountered
-    def delete(attr)
-        attr = symbolize(attr)
-        if @parameters.has_key?(attr)
-            @parameters.delete(attr)
-        else
-            raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}")
-        end
-    end
-
-    # iterate across the existing properties
-    def eachproperty
-        # properties() is a private method
-        properties().each { |property|
-            yield property
-        }
-    end
-
-    # retrieve the 'should' value for a specified property
-    def should(name)
-        name = attr_alias(name)
-        if prop = @parameters[name] and prop.is_a?(Puppet::Property)
-            return prop.should
-        else
-            return nil
-        end
-    end
-
-    # Create the actual attribute instance.  Requires either the attribute
-    # name or class as the first argument, then an optional hash of
-    # attributes to set during initialization.
-    def newattr(name, options = {})
-        if name.is_a?(Class)
-            klass = name
-            name = klass.name
-        end
-
-        unless klass = self.class.attrclass(name)
-            raise Puppet::Error, "Resource type %s does not support parameter %s" % [self.class.name, name]
-        end
-
-        if @parameters.include?(name)
-            raise Puppet::Error, "Parameter '%s' is already defined in %s" %
-                [name, self.ref]
-        end
-
-        if provider and ! provider.class.supports_parameter?(klass)
-            missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) }
-            info "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name]
-            return nil
-        end
-
-        # Add resource information at creation time, so it's available
-        # during validation.
-        options[:resource] = self
-        begin
-            # make sure the parameter doesn't have any errors
-            return @parameters[name] = klass.new(options)
-        rescue => detail
-            error = Puppet::Error.new("Parameter %s failed: %s" %
-                [name, detail])
-            error.set_backtrace(detail.backtrace)
-            raise error
-        end
-    end
-
-    # return the value of a parameter
-    def parameter(name)
-        unless name.is_a? Symbol
-            name = name.intern
-        end
-        return @parameters[name].value
-    end
-
-    # Is the named property defined?
-    def propertydefined?(name)
-        unless name.is_a? Symbol
-            name = name.intern
-        end
-        return @parameters.include?(name)
-    end
-
-    # return an actual type by name; to return the value, use 'inst[name]'
-    # FIXME this method should go away
-    def property(name)
-        if obj = @parameters[symbolize(name)] and obj.is_a?(Puppet::Property)
-            return obj
-        else
-            return nil
-        end
-    end
-
-#    def set(name, value)
-#        send(name.to_s + "=", value)
-#    end
-#
-#    def get(name)
-#        send(name)
-#    end
-
-    # For any parameters or properties that have defaults and have not yet been
-    # set, set them now.  This method can be handed a list of attributes,
-    # and if so it will only set defaults for those attributes.
-    def setdefaults(*ary)
-        #self.class.eachattr(*ary) { |klass, type|
-        self.class.eachattr(*ary) { |klass, type|
-            # not many attributes will have defaults defined, so we short-circuit
-            # those away
-            next unless klass.method_defined?(:default)
-            next if @parameters[klass.name]
-
-            next unless obj = self.newattr(klass)
-
-            # We have to check for nil values, not "truth", so we allow defaults
-            # to false.
-            value = obj.default and ! value.nil?
-            if ! value.nil?
-                obj.value = value
-            else
-                @parameters.delete(obj.name)
-            end
-        }
-    end
-
-    # Convert our object to a hash.  This just includes properties.
-    def to_hash
-        rethash = {}
-    
-        @parameters.each do |name, obj|
-            rethash[name] = obj.value
-        end
-
-        rethash
-    end
-
-    # Return a specific value for an attribute.
-    def value(name)
-        name = attr_alias(name)
-
-        if obj = @parameters[name] and obj.respond_to?(:value)
-            return obj.value
-        else
-            return nil
-        end
-    end
-
-    # Meta-parameter methods:  These methods deal with the results
-    # of specifying metaparameters
-
-    private
-
-    # Return all of the property objects, in the order specified in the
-    # class.
-    def properties
-        #debug "%s has %s properties" % [self, at parameters.length]
-        props = self.class.properties.collect { |prop|
-            @parameters[prop.name]
-        }.find_all { |p|
-            ! p.nil?
-        }.each do |prop|
-            unless prop.is_a?(Puppet::Property)
-                raise Puppet::DevError, "got a non-property %s(%s)" %
-                    [prop.class, prop.class.name]
-            end
-        end
-
-        props
-    end
-
-    public
-
-    ###############################
-    # Code related to the closure-like behaviour of the resource classes.
-    attr_writer :implicit
-
-    # Is this type's name isomorphic with the object?  That is, if the
-    # name conflicts, does it necessarily mean that the objects conflict?
-    # Defaults to true.
-    def self.isomorphic?
-        if defined? @isomorphic
-            return @isomorphic
-        else
-            return true
-        end
-    end
-
-    def implicit?
-        if defined? @implicit and @implicit
-            return true
-        else
-            return false
-        end
-    end
-
-    def isomorphic?
-        self.class.isomorphic?
-    end
-
-    # is the instance a managed instance?  A 'yes' here means that
-    # the instance was created from the language, vs. being created
-    # in order resolve other questions, such as finding a package
-    # in a list
-    def managed?
-        # Once an object is managed, it always stays managed; but an object
-        # that is listed as unmanaged might become managed later in the process,
-        # so we have to check that every time
-        if defined? @managed and @managed
-            return @managed
-        else
-            @managed = false
-            properties.each { |property|
-                s = property.should
-                if s and ! property.class.unmanaged
-                    @managed = true
-                    break
-                end
-            }
-            return @managed
-        end
-    end
-
-    ###############################
-    # Code related to the container behaviour.
-    def self.depthfirst?
-        if defined? @depthfirst
-            return @depthfirst
-        else
-            return false
-        end
-    end
-    
-    def depthfirst?
-        self.class.depthfirst?
-    end
-
-    # Add a hook for testing for recursion.
-    def parentof?(child)
-        if (self == child)
-            debug "parent is equal to child"
-            return true
-        elsif defined? @parent and @parent.parentof?(child)
-            debug "My parent is parent of child"
-            return true
-        else
-            return false
-        end
-    end
-
-    # Remove an object.  The argument determines whether the object's
-    # subscriptions get eliminated, too.
-    def remove(rmdeps = true)
-        # This is hackish (mmm, cut and paste), but it works for now, and it's
-        # better than warnings.
-        @parameters.each do |name, obj|
-            obj.remove
-        end
-        @parameters.clear
-        self.class.delete(self)
-
-        @parent = nil
-
-        # Remove the reference to the provider.
-        if self.provider
-            @provider.clear
-            @provider = nil
-        end
-    end
-
-    ###############################
-    # Code related to evaluating the resources.
-
-    # This method is responsible for collecting property changes we always
-    # descend into the children before we evaluate our current properties.
-    # This returns any changes resulting from testing, thus 'collect' rather
-    # than 'each'.
-    def evaluate
-        if self.provider.is_a?(Puppet::Provider)
-            unless provider.class.suitable?
-                raise Puppet::Error, "Provider %s is not functional on this platform" % provider.class.name
-            end
-        end
-        #Puppet.err "Evaluating %s" % self.path.join(":")
-        unless defined? @evalcount
-            self.err "No evalcount defined on '%s' of type '%s'" %
-                [self.title,self.class]
-            @evalcount = 0
-        end
-        @evalcount += 1
-
-        if p = self.provider and p.respond_to?(:prefetch)
-            p.prefetch
-        end
-
-        # this only operates on properties, not properties + children
-        # it's important that we call retrieve() on the type instance,
-        # not directly on the property, because it allows the type to override
-        # the method, like pfile does
-        currentvalues = self.retrieve
-
-        changes = propertychanges(currentvalues).flatten
-
-        # now record how many changes we've resulted in
-        if changes.length > 0
-            self.debug "%s change(s)" %
-                [changes.length]
-        end
-
-        # If we're in noop mode, we don't want to store the checked time,
-        # because it will result in the resource not getting scheduled if
-        # someone were to apply the catalog in non-noop mode.
-        # We're going to go ahead and record that we checked if there were
-        # no changes, since it's unlikely it will affect the scheduling.
-        noop = noop?
-        if ! noop or (noop && changes.length == 0)
-            self.cache(:checked, Time.now)
-        end
-        return changes.flatten
-    end
-
-    # Flush the provider, if it supports it.  This is called by the
-    # transaction.
-    def flush
-        if self.provider and self.provider.respond_to?(:flush)
-            self.provider.flush
-        end
-    end
-
-    # if all contained objects are in sync, then we're in sync
-    # FIXME I don't think this is used on the type instances any more,
-    # it's really only used for testing
-    def insync?(is)
-        insync = true
-        
-        if property = @parameters[:ensure]
-            unless is.include? property
-               raise Puppet::DevError,
-                        "The is value is not in the is array for '%s'" %
-                        [property.name]
-            end
-            ensureis = is[property]           
-            if property.insync?(ensureis) and property.should == :absent
-                return true
-            end
-        end
-
-        properties.each { |property|
-            unless is.include? property
-               raise Puppet::DevError,
-                        "The is value is not in the is array for '%s'" %
-                        [property.name]
-            end
-
-            propis = is[property]
-            unless property.insync?(propis)
-                property.debug("Not in sync: %s vs %s" %
-                    [propis.inspect, property.should.inspect])
-                insync = false
-            #else
-            #    property.debug("In sync")
-            end
-        }
-
-        #self.debug("%s sync status is %s" % [self,insync])
-        return insync
-    end
-        
-    # retrieve the current value of all contained properties
-    def retrieve
-        return currentpropvalues
-    end
-    
-    # Get a hash of the current properties.  Returns a hash with
-    # the actual property instance as the key and the current value
-    # as the, um, value.
-    def currentpropvalues
-        # It's important to use the 'properties' method here, as it follows the order
-        # in which they're defined in the class.  It also guarantees that 'ensure'
-        # is the first property, which is important for skipping 'retrieve' on
-        # all the properties if the resource is absent.
-        ensure_state = false
-        return properties().inject({}) do | prophash, property|
-            if property.name == :ensure
-                ensure_state = property.retrieve
-                prophash[property] = ensure_state
-            else
-                if ensure_state == :absent
-                    prophash[property] = :absent
-                else
-                    prophash[property] = property.retrieve
-                end
-            end
-            prophash
-        end
-    end
-
-    # Are we running in noop mode?
-    def noop?
-        if defined?(@noop)
-            @noop
-        else
-            Puppet[:noop]
-        end
-    end
-
-    def noop
-        noop?
-    end
-     
-    # Retrieve the changes associated with all of the properties.
-    def propertychanges(currentvalues)
-        # If we are changing the existence of the object, then none of
-        # the other properties matter.
-        changes = []
-        ensureparam = @parameters[:ensure]
-
-        # This allows resource types to have 'ensure' be a parameter, which allows them to
-        # just pass the parameter on to other generated resources.
-        ensureparam = nil unless ensureparam.is_a?(Puppet::Property)
-        if ensureparam && !currentvalues.include?(ensureparam)
-            raise Puppet::DevError, "Parameter ensure defined but missing from current values"
-        end
-
-        if ensureparam and ! ensureparam.insync?(currentvalues[ensureparam])
-            changes << Puppet::Transaction::Change.new(ensureparam, currentvalues[ensureparam])
-        # Else, if the 'ensure' property is correctly absent, then do
-        # nothing
-        elsif ensureparam and currentvalues[ensureparam] == :absent
-            return []
-        else
-            changes = properties().find_all { |property|
-                currentvalues[property] ||= :absent
-                ! property.insync?(currentvalues[property])
-            }.collect { |property|
-                Puppet::Transaction::Change.new(property, currentvalues[property])
-            }
-        end
-
-        if Puppet[:debug] and changes.length > 0
-            self.debug("Changing " + changes.collect { |ch| ch.property.name }.join(","))
-        end
-
-        changes
-    end
-
-    ###############################
-    # Code related to managing resource instances.
-    require 'puppet/transportable'
-
-    # Make 'new' private, so people have to use create instead.
-    class << self
-        private :new
-    end
-
-    # retrieve a named instance of the current type
-    def self.[](name)
-        @objects[name] || @aliases[name]
-    end
-
-    # add an instance by name to the class list of instances
-    def self.[]=(name,object)
-        newobj = nil
-        if object.is_a?(Puppet::Type)
-            newobj = object
-        else
-            raise Puppet::DevError, "must pass a Puppet::Type object"
-        end
-
-        if exobj = @objects[name] and self.isomorphic?
-            msg = "Object '%s[%s]' already exists" %
-                [newobj.class.name, name]
-
-            if exobj.file and exobj.line
-                msg += ("in file %s at line %s" %
-                    [object.file, object.line])
-            end
-            if object.file and object.line
-                msg += ("and cannot be redefined in file %s at line %s" %
-                    [object.file, object.line])
-            end
-            error = Puppet::Error.new(msg)
-            raise error
-        else
-            #Puppet.info("adding %s of type %s to class list" %
-            #    [name,object.class])
-            @objects[name] = newobj
-        end
-    end
-
-    # Create an alias.  We keep these in a separate hash so that we don't encounter
-    # the objects multiple times when iterating over them.
-    def self.alias(name, obj)
-        if @objects.include?(name)
-            unless @objects[name] == obj
-                raise Puppet::Error.new(
-                    "Cannot create alias %s: object already exists" %
-                    [name]
-                )
-            end
-        end
-
-        if @aliases.include?(name)
-            unless @aliases[name] == obj
-                raise Puppet::Error.new(
-                    "Object %s already has alias %s" %
-                    [@aliases[name].name, name]
-                )
-            end
-        end
-
-        @aliases[name] = obj
-    end
-
-    # remove all of the instances of a single type
-    def self.clear
-        if defined? @objects
-            @objects.each do |name, obj|
-                obj.remove(true)
-            end
-            @objects.clear
-        end
-        if defined? @aliases
-            @aliases.clear
-        end
-    end
-
-    # Force users to call this, so that we can merge objects if
-    # necessary.
-    def self.create(args)
-        # Don't modify the original hash; instead, create a duplicate and modify it.
-        # We have to dup and use the ! so that it stays a TransObject if it is
-        # one.
-        hash = args.dup
-        symbolizehash!(hash)
-
-        # If we're the base class, then pass the info on appropriately
-        if self == Puppet::Type
-            type = nil
-            if hash.is_a? Puppet::TransObject
-                type = hash.type
-            else
-                # If we're using the type to determine object type, then delete it
-                if type = hash[:type]
-                    hash.delete(:type)
-                end
-            end
-
-            # If they've specified a type and called on the base, then
-            # delegate to the subclass.
-            if type
-                if typeklass = self.type(type)
-                    return typeklass.create(hash)
-                else
-                    raise Puppet::Error, "Unknown type %s" % type
-                end
-            else
-                raise Puppet::Error, "No type found for %s" % hash.inspect
-            end
-        end
-
-        # Handle this new object being implicit
-        implicit = hash[:implicit] || false
-        if hash.include?(:implicit)
-            hash.delete(:implicit)
-        end
-
-        name = nil
-        unless hash.is_a? Puppet::TransObject
-            hash = self.hash2trans(hash)
-        end
-
-        # XXX This will have to change when transobjects change to using titles
-        title = hash.name
-
-        # if the object already exists
-        if self.isomorphic? and retobj = self[title]
-            # if only one of our objects is implicit, then it's easy to see
-            # who wins -- the non-implicit one.
-            if retobj.implicit? and ! implicit
-                Puppet.notice "Removing implicit %s" % retobj.title
-                # Remove all of the objects, but do not remove their subscriptions.
-                retobj.remove(false)
-
-                # now pass through and create the new object
-            elsif implicit
-                Puppet.debug "Ignoring implicit %s[%s]" % [self.name, title]
-                return nil
-            else
-                raise Puppet::Error, "%s is already being managed" % retobj.ref
-            end
-        end
-
-        # create it anew
-        # if there's a failure, destroy the object if it got that far, but raise
-        # the error.
-        begin
-            obj = new(hash)
-        rescue => detail
-            Puppet.err "Could not create %s: %s" % [title, detail.to_s]
-            if obj
-                obj.remove(true)
-            elsif obj = self[title]
-                obj.remove(true)
-            end
-            raise
-        end
-
-        if implicit
-            obj.implicit = true
-        end
-
-        # Store the object by title
-        self[obj.title] = obj
-
-        return obj
-    end
-
-    # remove a specified object
-    def self.delete(resource)
-        return unless defined? @objects
-        if @objects.include?(resource.title)
-            @objects.delete(resource.title)
-        end
-        if @aliases.include?(resource.title)
-            @aliases.delete(resource.title)
-        end
-        if @aliases.has_value?(resource)
-            names = []
-            @aliases.each do |name, otherres|
-                if otherres == resource
-                    names << name
-                end
-            end
-            names.each { |name| @aliases.delete(name) }
-        end
-    end
-
-    # iterate across each of the type's instances
-    def self.each
-        return unless defined? @objects
-        @objects.each { |name,instance|
-            yield instance
-        }
-    end
-
-    # does the type have an object with the given name?
-    def self.has_key?(name)
-        return @objects.has_key?(name)
-    end
-
-    # Convert a hash to a TransObject.
-    def self.hash2trans(hash)
-        title = nil
-        if hash.include? :title
-            title = hash[:title]
-            hash.delete(:title)
-        elsif hash.include? self.namevar
-            title = hash[self.namevar]
-            hash.delete(self.namevar)
-
-            if hash.include? :name
-                raise ArgumentError, "Cannot provide both name and %s to %s" %
-                    [self.namevar, self.name]
-            end
-        elsif hash[:name]
-            title = hash[:name]
-            hash.delete :name
-        end
-
-        if catalog = hash[:catalog]
-            hash.delete(:catalog)
-        end
-
-        raise(Puppet::Error, "You must specify a title for objects of type %s" % self.to_s) unless title
-
-        if hash.include? :type
-            unless self.validattr? :type
-                hash.delete :type
-            end
-        end
-
-        # okay, now make a transobject out of hash
-        begin
-            trans = Puppet::TransObject.new(title, self.name.to_s)
-            trans.catalog = catalog if catalog
-            hash.each { |param, value|
-                trans[param] = value
-            }
-        rescue => detail
-            raise Puppet::Error, "Could not create %s: %s" %
-                [name, detail]
-        end
-
-        return trans
-    end
-
-    # Retrieve all known instances.  Either requires providers or must be overridden.
-    def self.instances
-        unless defined?(@providers) and ! @providers.empty?
-            raise Puppet::DevError, "%s has no providers and has not overridden 'instances'" % self.name
-        end
-
-        # Put the default provider first, then the rest of the suitable providers.
-        provider_instances = {}
-        providers_by_source.collect do |provider|
-            provider.instances.collect do |instance|
-                # First try to get the resource if it already exists
-                # Skip instances that map to a managed resource with a different provider
-                next if resource = self[instance.name] and resource.provider.class != instance.class
-
-                # We always want to use the "first" provider instance we find, unless the resource
-                # is already managed and has a different provider set
-                if other = provider_instances[instance.name]
-                    Puppet.warning "%s %s found in both %s and %s; skipping the %s version" %
-                        [self.name.to_s.capitalize, instance.name, other.class.name, instance.class.name, instance.class.name]
-                    next
-                end
-                provider_instances[instance.name] = instance
-
-                if resource
-                    resource.provider = instance
-                    resource
-                else
-                    create(:name => instance.name, :provider => instance, :check => :all)
-                end
-            end
-        end.flatten.compact
-    end
-
-    # Return a list of one suitable provider per source, with the default provider first.
-    def self.providers_by_source
-        # Put the default provider first, then the rest of the suitable providers.
-        sources = []
-        [defaultprovider, suitableprovider].flatten.uniq.collect do |provider|
-            next if sources.include?(provider.source)
-
-            sources << provider.source
-            provider
-        end.compact
-    end
-
-    # Create the path for logging and such.
-    def pathbuilder
-        if p = parent
-            [p.pathbuilder, self.ref].flatten
-        else
-            [self.ref]
-        end
-    end
-
-    ###############################
-    # Add all of the meta parameters.
-    newmetaparam(:noop) do
-        desc "Boolean flag indicating whether work should actually
-            be done."
-            
-        newvalues(:true, :false)
-        munge do |value|
-            case value
-            when true, :true, "true": @resource.noop = true
-            when false, :false, "false": @resource.noop = false
-            end
-        end
-    end
-
-    newmetaparam(:schedule) do
-        desc "On what schedule the object should be managed.  You must create a
-            schedule object, and then reference the name of that object to use
-            that for your schedule::
-
-                schedule { daily:
-                    period => daily,
-                    range => \"2-4\"
-                }
-
-                exec { \"/usr/bin/apt-get update\":
-                    schedule => daily
-                }
-
-            The creation of the schedule object does not need to appear in the
-            configuration before objects that use it."
-    end
-
-    newmetaparam(:check) do
-        desc "Propertys which should have their values retrieved
-            but which should not actually be modified.  This is currently used
-            internally, but will eventually be used for querying, so that you
-            could specify that you wanted to check the install state of all
-            packages, and then query the Puppet client daemon to get reports
-            on all packages."
-
-        munge do |args|
-            # If they've specified all, collect all known properties
-            if args == :all
-                args = @resource.class.properties.find_all do |property|
-                    # Only get properties supported by our provider
-                    if @resource.provider
-                        @resource.provider.class.supports_parameter?(property)
-                    else
-                        true
-                    end
-                end.collect do |property|
-                    property.name
-                end
-            end
-
-            unless args.is_a?(Array)
-                args = [args]
-            end
-
-            unless defined? @resource
-                self.devfail "No parent for %s, %s?" %
-                    [self.class, self.name]
-            end
-
-            args.each { |property|
-                unless property.is_a?(Symbol)
-                    property = property.intern
-                end
-                next if @resource.propertydefined?(property)
-
-                unless propertyklass = @resource.class.validproperty?(property)
-                    if @resource.class.validattr?(property)
-                        next
-                    else
-                        raise Puppet::Error, "%s is not a valid attribute for %s" %
-                            [property, self.class.name]
-                    end
-                end
-                next unless propertyklass.checkable?
-                @resource.newattr(property)
-            }
-        end
-    end
-    
-    # We've got four relationship metaparameters, so this method is used
-    # to reduce code duplication between them.
-    def munge_relationship(param, values)
-        # We need to support values passed in as an array or as a
-        # resource reference.
-        result = []
-        
-        # 'values' could be an array or a reference.  If it's an array,
-        # it could be an array of references or an array of arrays.
-        if values.is_a?(Puppet::Type)
-            result << [values.class.name, values.title]
-        else
-            unless values.is_a?(Array)
-                devfail "Relationships must be resource references"
-            end
-            if values[0].is_a?(String) or values[0].is_a?(Symbol)
-                # we're a type/title array reference
-                values[0] = symbolize(values[0])
-                result << values
-            else
-                # we're an array of stuff
-                values.each do |value|
-                    if value.is_a?(Puppet::Type)
-                        result << [value.class.name, value.title]
-                    elsif value.is_a?(Array)
-                        value[0] = symbolize(value[0])
-                        result << value
-                    else
-                        devfail "Invalid relationship %s" % value.inspect
-                    end
-                end
-            end
-        end
-        
-        if existing = self[param]
-            result = existing + result
-        end
-        
-        result
-    end
-
-    newmetaparam(:loglevel) do
-        desc "Sets the level that information will be logged.
-             The log levels have the biggest impact when logs are sent to
-             syslog (which is currently the default)."
-        defaultto :notice
-
-        newvalues(*Puppet::Util::Log.levels)
-        newvalues(:verbose)
-
-        munge do |loglevel|
-            val = super(loglevel)
-            if val == :verbose
-                val = :info 
-            end        
-            val
-        end
-    end
-
-    newmetaparam(:alias) do
-        desc "Creates an alias for the object.  Puppet uses this internally when you
-            provide a symbolic name::
-            
-                file { sshdconfig:
-                    path => $operatingsystem ? {
-                        solaris => \"/usr/local/etc/ssh/sshd_config\",
-                        default => \"/etc/ssh/sshd_config\"
-                    },
-                    source => \"...\"
-                }
-
-                service { sshd:
-                    subscribe => file[sshdconfig]
-                }
-
-            When you use this feature, the parser sets ``sshdconfig`` as the name,
-            and the library sets that as an alias for the file so the dependency
-            lookup for ``sshd`` works.  You can use this parameter yourself,
-            but note that only the library can use these aliases; for instance,
-            the following code will not work::
-
-                file { \"/etc/ssh/sshd_config\":
-                    owner => root,
-                    group => root,
-                    alias => sshdconfig
-                }
-
-                file { sshdconfig:
-                    mode => 644
-                }
-
-            There's no way here for the Puppet parser to know that these two stanzas
-            should be affecting the same file.
-
-            See the `LanguageTutorial language tutorial`:trac: for more information.
-            
-            "
-
-        munge do |aliases|
-            unless aliases.is_a?(Array)
-                aliases = [aliases]
-            end
-
-            raise(ArgumentError, "Cannot add aliases without a catalog") unless @resource.catalog
-
-            aliases.each do |other|
-                if obj = @resource.catalog.resource(@resource.class.name, other)
-                    unless obj.object_id == @resource.object_id
-                        self.fail("%s can not create alias %s: object already exists" % [@resource.title, other])
-                    end
-                    next
-                end
-
-                # LAK:FIXME Old-school, add the alias to the class.
-                @resource.class.alias(other, @resource)
-
-                # Newschool, add it to the catalog.
-                @resource.catalog.alias(@resource, other)
-            end
-        end
-    end
-
-    newmetaparam(:tag) do
-        desc "Add the specified tags to the associated resource.  While all resources
-            are automatically tagged with as much information as possible
-            (e.g., each class and definition containing the resource), it can
-            be useful to add your own tags to a given resource.
-
-            Tags are currently useful for things like applying a subset of a
-            host's configuration::
-                
-                puppetd --test --tags mytag
-
-            This way, when you're testing a configuration you can run just the
-            portion you're testing."
-
-        munge do |tags|
-            tags = [tags] unless tags.is_a? Array
-
-            tags.each do |tag|
-                @resource.tag(tag)
-            end
-        end
-    end
-    
-    class RelationshipMetaparam < Puppet::Parameter
-        class << self
-            attr_accessor :direction, :events, :callback, :subclasses
-        end
-        
-        @subclasses = []
-        
-        def self.inherited(sub)
-            @subclasses << sub
-        end
-        
-        def munge(rels)
-            @resource.munge_relationship(self.class.name, rels)
-        end
-
-        def validate_relationship
-            @value.each do |value|
-                unless @resource.catalog.resource(*value)
-                    description = self.class.direction == :in ? "dependency" : "dependent"
-                    fail Puppet::Error, "Could not find %s %s[%s] for %s" % 
-                        [description, value[0].to_s.capitalize, value[1], resource.ref]
-                end
-            end
-        end
-        
-        # Create edges from each of our relationships.    :in
-        # relationships are specified by the event-receivers, and :out
-        # relationships are specified by the event generator.  This
-        # way 'source' and 'target' are consistent terms in both edges
-        # and events -- that is, an event targets edges whose source matches
-        # the event's source.  The direction of the relationship determines
-        # which resource is applied first and which resource is considered
-        # to be the event generator.
-        def to_edges
-            @value.collect do |value|
-                # we just have a name and a type, and we need to convert it
-                # to an object...
-                tname, name = value
-                reference = Puppet::ResourceReference.new(tname, name)
-                
-                # Either of the two retrieval attempts could have returned
-                # nil.
-                unless object = reference.resolve
-                    self.fail "Could not retrieve dependency '%s' of %s" % [reference, @resource.ref]
-                end
-
-                # Are we requiring them, or vice versa?  See the method docs
-                # for futher info on this.
-                if self.class.direction == :in
-                    source = object
-                    target = @resource
-                else
-                    source = @resource
-                    target = object
-                end
-
-                if method = self.class.callback
-                    subargs = {
-                        :event => self.class.events,
-                        :callback => method
-                    }
-                    self.debug("subscribes to %s" % [object.ref])
-                else
-                    # If there's no callback, there's no point in even adding
-                    # a label.
-                    subargs = nil
-                    self.debug("requires %s" % [object.ref])
-                end
-                
-                rel = Puppet::Relationship.new(source, target, subargs)
-            end
-        end
-    end
-    
-    def self.relationship_params
-        RelationshipMetaparam.subclasses
-    end
-
-
-    # Note that the order in which the relationships params is defined
-    # matters.  The labelled params (notify and subcribe) must be later,
-    # so that if both params are used, those ones win.  It's a hackish
-    # solution, but it works.
-
-    newmetaparam(:require, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :NONE}) do
-        desc "One or more objects that this object depends on.
-            This is used purely for guaranteeing that changes to required objects
-            happen before the dependent object.  For instance::
-            
-                # Create the destination directory before you copy things down
-                file { \"/usr/local/scripts\":
-                    ensure => directory
-                }
-
-                file { \"/usr/local/scripts/myscript\":
-                    source => \"puppet://server/module/myscript\",
-                    mode => 755,
-                    require => File[\"/usr/local/scripts\"]
-                }
-
-            Multiple dependencies can be specified by providing a comma-seperated list
-            of resources, enclosed in square brackets::
-
-                require => [ File[\"/usr/local\"], File[\"/usr/local/scripts\"] ]
-
-            Note that Puppet will autorequire everything that it can, and
-            there are hooks in place so that it's easy for resources to add new
-            ways to autorequire objects, so if you think Puppet could be
-            smarter here, let us know.
-
-            In fact, the above code was redundant -- Puppet will autorequire
-            any parent directories that are being managed; it will
-            automatically realize that the parent directory should be created
-            before the script is pulled down.
-            
-            Currently, exec resources will autorequire their CWD (if it is
-            specified) plus any fully qualified paths that appear in the
-            command.   For instance, if you had an ``exec`` command that ran
-            the ``myscript`` mentioned above, the above code that pulls the
-            file down would be automatically listed as a requirement to the
-            ``exec`` code, so that you would always be running againts the
-            most recent version.
-            "
-    end
-
-    newmetaparam(:subscribe, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :ALL_EVENTS, :callback => :refresh}) do
-        desc "One or more objects that this object depends on.  Changes in the
-            subscribed to objects result in the dependent objects being
-            refreshed (e.g., a service will get restarted).  For instance::
-            
-                class nagios {
-                    file { \"/etc/nagios/nagios.conf\":
-                        source => \"puppet://server/module/nagios.conf\",
-                        alias => nagconf # just to make things easier for me
-                    }
-                    service { nagios:
-                        running => true,
-                        subscribe => File[nagconf]
-                    }
-                }
-	 		
-            Currently the ``exec``, ``mount`` and ``service`` type support
-            refreshing.
-            "
-    end
-
-    newmetaparam(:before, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :NONE}) do
-        desc %{This parameter is the opposite of **require** -- it guarantees
-            that the specified object is applied later than the specifying
-            object::
-
-                file { "/var/nagios/configuration":
-                    source  => "...",
-                    recurse => true,
-                    before => Exec["nagios-rebuid"]
-                }
-
-                exec { "nagios-rebuild":
-                    command => "/usr/bin/make",
-                    cwd => "/var/nagios/configuration"
-                }
-            
-            This will make sure all of the files are up to date before the
-            make command is run.}
-    end
-    
-    newmetaparam(:notify, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :ALL_EVENTS, :callback => :refresh}) do
-        desc %{This parameter is the opposite of **subscribe** -- it sends events
-            to the specified object::
-
-                file { "/etc/sshd_config":
-                    source => "....",
-                    notify => Service[sshd]
-                }
-
-                service { sshd:
-                    ensure => running
-                }
-            
-            This will restart the sshd service if the sshd config file changes.}
-    end
-
-    ###############################
-    # All of the provider plumbing for the resource types.
-    require 'puppet/provider'
-    require 'puppet/util/provider_features'
-
-    # Add the feature handling module.
-    extend Puppet::Util::ProviderFeatures
-
-    attr_reader :provider
-
-    # the Type class attribute accessors
-    class << self
-        attr_accessor :providerloader
-        attr_writer :defaultprovider
-    end
-
-    # Find the default provider.
-    def self.defaultprovider
-        unless defined? @defaultprovider and @defaultprovider
-            suitable = suitableprovider()
-
-            # Find which providers are a default for this system.
-            defaults = suitable.find_all { |provider| provider.default? }
-
-            # If we don't have any default we use suitable providers
-            defaults = suitable if defaults.empty?
-            max = defaults.collect { |provider| provider.defaultnum }.max
-            defaults = defaults.find_all { |provider| provider.defaultnum == max }
-
-            retval = nil
-            if defaults.length > 1
-                Puppet.warning(
-                    "Found multiple default providers for %s: %s; using %s" %
-                    [self.name, defaults.collect { |i| i.name.to_s }.join(", "),
-                        defaults[0].name]
-                )
-                retval = defaults.shift
-            elsif defaults.length == 1
-                retval = defaults.shift
-            else
-                raise Puppet::DevError, "Could not find a default provider for %s" %
-                    self.name
-            end
-
-            @defaultprovider = retval
-        end
-
-        return @defaultprovider
-    end
-
-    # Convert a hash, as provided by, um, a provider, into an instance of self.
-    def self.hash2obj(hash)
-        obj = nil
-        
-        namevar = self.namevar
-        unless hash.include?(namevar) and hash[namevar]
-            raise Puppet::DevError, "Hash was not passed with namevar"
-        end
-
-        # if the obj already exists with that name...
-        if obj = self[hash[namevar]]
-            # We're assuming here that objects with the same name
-            # are the same object, which *should* be the case, assuming
-            # we've set up our naming stuff correctly everywhere.
-
-            # Mark found objects as present
-            hash.each { |param, value|
-                if property = obj.property(param)
-                elsif val = obj[param]
-                    obj[param] = val
-                else
-                    # There is a value on disk, but it should go away
-                    obj[param] = :absent
-                end
-            }
-        else
-            # create a new obj, since no existing one seems to
-            # match
-            obj = self.create(namevar => hash[namevar])
-
-            # We can't just pass the hash in at object creation time,
-            # because it sets the should value, not the is value.
-            hash.delete(namevar)
-            hash.each { |param, value|
-                obj[param] = value unless obj.add_property_parameter(param)
-            }
-        end
-
-        return obj
-    end
-
-    # Retrieve a provider by name.
-    def self.provider(name)
-        name = Puppet::Util.symbolize(name)
-
-        # If we don't have it yet, try loading it.
-        unless @providers.has_key?(name)
-            @providerloader.load(name)
-        end
-        return @providers[name]
-    end
-
-    # Just list all of the providers.
-    def self.providers
-        @providers.keys
-    end
-
-    def self.validprovider?(name)
-        name = Puppet::Util.symbolize(name)
-
-        return (@providers.has_key?(name) && @providers[name].suitable?)
-    end
-
-    # Create a new provider of a type.  This method must be called
-    # directly on the type that it's implementing.
-    def self.provide(name, options = {}, &block)
-        name = Puppet::Util.symbolize(name)
-
-        if obj = @providers[name]
-            Puppet.debug "Reloading %s %s provider" % [name, self.name]
-            unprovide(name)
-        end
-
-        parent = if pname = options[:parent]
-            options.delete(:parent)
-            if pname.is_a? Class
-                pname
-            else
-                if provider = self.provider(pname)
-                    provider
-                else
-                    raise Puppet::DevError,
-                        "Could not find parent provider %s of %s" %
-                            [pname, name]
-                end
-            end
-        else
-            Puppet::Provider
-        end
-
-        options[:resource_type] ||= self
-
-        self.providify
-
-        provider = genclass(name,
-            :parent => parent,
-            :hash => @providers,
-            :prefix => "Provider",
-            :block => block,
-            :include => feature_module,
-            :extend => feature_module,
-            :attributes => options
-        )
-
-        return provider
-    end
-
-    # Make sure we have a :provider parameter defined.  Only gets called if there
-    # are providers.
-    def self.providify
-        return if @paramhash.has_key? :provider
-
-        newparam(:provider) do
-            desc "The specific backend for #{self.name.to_s} to use. You will
-                seldom need to specify this -- Puppet will usually discover the
-                appropriate provider for your platform."
-
-            # This is so we can refer back to the type to get a list of
-            # providers for documentation.
-            class << self
-                attr_accessor :parenttype
-            end
-
-            # We need to add documentation for each provider.
-            def self.doc
-                @doc + "  Available providers are:\n\n" + parenttype().providers.sort { |a,b|
-                    a.to_s <=> b.to_s
-                }.collect { |i|
-                    "* **%s**: %s" % [i, parenttype().provider(i).doc]
-                }.join("\n")
-            end
-
-            defaultto {
-                @resource.class.defaultprovider.name
-            }
-
-            validate do |provider_class|
-                provider_class = provider_class[0] if provider_class.is_a? Array
-                if provider_class.is_a?(Puppet::Provider)
-                    provider_class = provider_class.class.name
-                end
-
-                unless provider = @resource.class.provider(provider_class)
-                    raise ArgumentError, "Invalid %s provider '%s'" % [@resource.class.name, provider_class]
-                end
-            end
-
-            munge do |provider|
-                provider = provider[0] if provider.is_a? Array
-                if provider.is_a? String
-                    provider = provider.intern
-                end
-                @resource.provider = provider
-
-                if provider.is_a?(Puppet::Provider)
-                    provider.class.name
-                else
-                    provider
-                end
-            end
-        end.parenttype = self
-    end
-
-    def self.unprovide(name)
-        if @providers.has_key? name
-            rmclass(name,
-                :hash => @providers,
-                :prefix => "Provider"
-            )
-            if @defaultprovider and @defaultprovider.name == name
-                @defaultprovider = nil
-            end
-        end
-    end
-
-    # Return an array of all of the suitable providers.
-    def self.suitableprovider
-        if @providers.empty?
-            providerloader.loadall
-        end
-        @providers.find_all { |name, provider|
-            provider.suitable?
-        }.collect { |name, provider|
-            provider
-        }.reject { |p| p.name == :fake } # For testing
-    end
-
-    def provider=(name)
-        if name.is_a?(Puppet::Provider)
-            @provider = name
-            @provider.resource = self
-        elsif klass = self.class.provider(name)
-            @provider = klass.new(self)
-        else
-            raise ArgumentError, "Could not find %s provider of %s" %
-                [name, self.class.name]
-        end
-    end
-
-    ###############################
-    # All of the relationship code.
-
-    # Specify a block for generating a list of objects to autorequire.  This
-    # makes it so that you don't have to manually specify things that you clearly
-    # require.
-    def self.autorequire(name, &block)
-        @autorequires ||= {}
-        @autorequires[name] = block
-    end
-
-    # Yield each of those autorequires in turn, yo.
-    def self.eachautorequire
-        @autorequires ||= {}
-        @autorequires.each { |type, block|
-            yield(type, block)
-        }
-    end
-
-    # Figure out of there are any objects we can automatically add as
-    # dependencies.
-    def autorequire
-        reqs = []
-        self.class.eachautorequire { |type, block|
-            # Ignore any types we can't find, although that would be a bit odd.
-            next unless typeobj = Puppet.type(type)
-
-            # Retrieve the list of names from the block.
-            next unless list = self.instance_eval(&block)
-            unless list.is_a?(Array)
-                list = [list]
-            end
-
-            # Collect the current prereqs
-            list.each { |dep|
-                obj = nil
-                # Support them passing objects directly, to save some effort.
-                unless dep.is_a? Puppet::Type
-                    # Skip autorequires that we aren't managing
-                    unless dep = typeobj[dep]
-                        next
-                    end
-                end
-                
-                reqs << Puppet::Relationship.new(dep, self)
-            }
-        }
-        
-        return reqs
-    end
-
-    # Build the dependencies associated with an individual object.
-    def builddepends
-        # Handle the requires
-        self.class.relationship_params.collect do |klass|
-            if param = @parameters[klass.name]
-                param.to_edges
-            end
-        end.flatten.reject { |r| r.nil? }
-    end
-    
-    # Does this resource have a relationship with the other?  We have to
-    # check each object for both directions of relationship.
-    def requires?(other)
-        them = [other.class.name, other.title]
-        me = [self.class.name, self.title]
-        self.class.relationship_params.each do |param|
-            case param.direction
-            when :in: return true if v = self[param.name] and v.include?(them)
-            when :out: return true if v = other[param.name] and v.include?(me)
-            end
-        end
-        return false
-    end
-
-    # we've received an event
-    # we only support local events right now, so we can pass actual
-    # objects around, including the transaction object
-    # the assumption here is that container objects will pass received
-    # methods on to contained objects
-    # i.e., we don't trigger our children, our refresh() method calls
-    # refresh() on our children
-    def trigger(event, source)
-        trans = event.transaction
-        if @callbacks.include?(source)
-            [:ALL_EVENTS, event.event].each { |eventname|
-                if method = @callbacks[source][eventname]
-                    if trans.triggered?(self, method) > 0
-                        next
-                    end
-                    if self.respond_to?(method)
-                        self.send(method)
-                    end
-
-                    trans.triggered(self, method)
-                end
-            }
-        end
-    end
-    
-    # Unsubscribe from a given object, possibly with a specific event.
-    def unsubscribe(object, event = nil)
-        # First look through our own relationship params
-        [:require, :subscribe].each do |param|
-            if values = self[param]
-                newvals = values.reject { |d|
-                    d == [object.class.name, object.title]
-                }
-                if newvals.length != values.length
-                    self.delete(param)
-                    self[param] = newvals
-                end
-            end
-        end
-    end
-
-    ###############################
-    # All of the scheduling code.
-
-    # Look up the schedule and set it appropriately.  This is done after
-    # the instantiation phase, so that the schedule can be anywhere in the
-    # file.
-    def schedule
-        unless defined? @schedule
-            if name = self[:schedule]
-                if sched = Puppet.type(:schedule)[name]
-                    @schedule = sched
-                else
-                    self.fail "Could not find schedule %s" % name
-                end
-            else
-                @schedule = nil
-            end
-        end
-        @schedule
-    end
-
-    # Check whether we are scheduled to run right now or not.
-    def scheduled?
-        return true if Puppet[:ignoreschedules]
-        return true unless schedule = self.schedule
-
-        # We use 'checked' here instead of 'synced' because otherwise we'll
-        # end up checking most resources most times, because they will generally
-        # have been synced a long time ago (e.g., a file only gets updated
-        # once a month on the server and its schedule is daily; the last sync time
-        # will have been a month ago, so we'd end up checking every run).
-        return schedule.match?(self.cached(:checked).to_i)
-    end
-
-    ###############################
-    # All of the tagging code.
-    attr_reader :tags
-
-    # Add a new tag.
-    def tag(tag)
-        tag = tag.intern if tag.is_a? String
-        unless @tags.include? tag
-            @tags << tag
-        end
-    end
-
-    # Define the initial list of tags.
-    def tags=(list)
-        list = [list] unless list.is_a? Array
-
-        @tags = list.collect do |t|
-            case t
-            when String: t.intern
-            when Symbol: t
-            else
-                self.warning "Ignoring tag %s of type %s" % [tag.inspect, tag.class]
-            end
-        end
-
-        @tags << self.class.name unless @tags.include?(self.class.name)
-    end
-
-    # Figure out of any of the specified tags apply to this object.  This is an
-    # OR operation.
-    def tagged?(tags)
-        tags = [tags] unless tags.is_a? Array
-
-        tags = tags.collect { |t| t.intern }
-
-        return tags.find { |tag| @tags.include? tag }
-    end
+    # Nearly all of the code in this class is stored in files in the
+    # metatype/ directory.  This is a temporary measure until I get a chance
+    # to refactor this class entirely.  There's still more simplification to
+    # do, but this works for now.
+    require 'puppet/metatype/attributes'
+    require 'puppet/metatype/closure'
+    require 'puppet/metatype/container'
+    require 'puppet/metatype/evaluation'
+    require 'puppet/metatype/instances'
+    require 'puppet/metatype/metaparams'
+    require 'puppet/metatype/providers'
+    require 'puppet/metatype/relationships'
+    require 'puppet/metatype/schedules'
+    require 'puppet/metatype/tags'
 
     # Types (which map to resources in the languages) are entirely composed of
     # attribute value pairs.  Generally, Puppet calls any of these things an
@@ -2510,6 +415,7 @@ class Type
 end # Puppet::Type
 end
 
+require 'puppet/propertychange'
 require 'puppet/provider'
 
 # Always load these types.
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 371571f..3518e8b 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -368,7 +368,7 @@ module Puppet
                         Find.find(self[:path]) do |f|
                             if File.file?(f)
                                 sum = backup.backup(f)
-                                self.notice "Filebucketed %s to %s with sum %s" %
+                                self.info "Filebucketed %s to %s with sum %s" %
                                     [f, backup.name, sum]
                             end
                         end
@@ -403,7 +403,7 @@ module Puppet
                 case backup
                 when Puppet::Network::Client.client(:Dipper):
                     sum = backup.backup(file)
-                    self.notice "Filebucketed to %s with sum %s" %
+                    self.info "Filebucketed to %s with sum %s" %
                         [backup.name, sum]
                     return true
                 when String:
@@ -849,8 +849,6 @@ module Puppet
             # Keep track of all the files we found in the source, so we can purge
             # appropriately.
             sourced = []
-
-            success = false
             
             @parameters[:source].should.each do |source|
                 sourceobj, path = uri2obj(source)
@@ -865,8 +863,6 @@ module Puppet
                 if desc == "" 
                     next
                 end
-
-                success = true
             
                 # Now create a new child for every file returned in the list.
                 result += desc.split("\n").collect { |line|
@@ -902,11 +898,6 @@ module Puppet
                     return [result, sourced]
                 end
             end
-
-            unless success
-                raise Puppet::Error, "None of the provided sources exist"
-            end
-
             return [result, sourced]
         end
 
@@ -1157,5 +1148,4 @@ module Puppet
     require 'puppet/type/file/group'
     require 'puppet/type/file/mode'
     require 'puppet/type/file/type'
-    require 'puppet/type/file/selcontext'  # SELinux file context
 end
diff --git a/lib/puppet/type/file/checksum.rb b/lib/puppet/type/file/checksum.rb
index 785ed0f..3be147c 100755
--- a/lib/puppet/type/file/checksum.rb
+++ b/lib/puppet/type/file/checksum.rb
@@ -53,9 +53,6 @@ Puppet::Type.type(:file).newproperty(:checksum) do
         else
             if FileTest.directory?(@resource[:path])
                 return :time
-            elsif @resource[:source] and value.to_s != "md5"
-                 self.warning("Files with source set must use md5 as checksum. Forcing to md5 from %s for %s" % [ value, @resource[:path] ])
-                return :md5
             else
                 return symbolize(value)
             end
@@ -164,7 +161,6 @@ Puppet::Type.type(:file).newproperty(:checksum) do
 
         checktype = :mtime if checktype == :timestamp
         checktype = :ctime if checktype == :time
-        self.should = checktype = :md5 if @resource.property(:source)
 
         file ||= @resource[:path]
 
diff --git a/lib/puppet/type/file/ensure.rb b/lib/puppet/type/file/ensure.rb
index a9ddc2d..0d21712 100755
--- a/lib/puppet/type/file/ensure.rb
+++ b/lib/puppet/type/file/ensure.rb
@@ -138,6 +138,11 @@ module Puppet
         # We have to treat :present specially, because it works with any
         # type of file.
         def insync?(currentvalue)
+            if property = @resource.property(:source) and ! property.described?
+                warning "No specified sources exist"
+                return true
+            end
+
             if self.should == :present
                 if currentvalue.nil? or currentvalue == :absent
                     return false
diff --git a/lib/puppet/type/file/group.rb b/lib/puppet/type/file/group.rb
index 56883ad..cc482ff 100755
--- a/lib/puppet/type/file/group.rb
+++ b/lib/puppet/type/file/group.rb
@@ -1,10 +1,6 @@
-require 'puppet/util/posix'
-
 # Manage file group ownership.
 module Puppet
     Puppet.type(:file).newproperty(:group) do
-        include Puppet::Util::POSIX
-
         require 'etc'
         desc "Which group should own the file.  Argument can be either group
             name or group ID."
@@ -46,23 +42,32 @@ module Puppet
             end
         end
 
-        def insync?(current)
-            @should.each do |value|
-                if value =~ /^\d+$/
-                    gid = Integer(value)
-                elsif value.is_a?(String)
-                    fail "Could not find group %s" % value unless gid = gid(value)
-                else
-                    gid = value
+        def retrieve
+            if self.should
+                @should = @should.collect do |val|
+                    unless val.is_a?(Integer)
+                        if tmp = validgroup?(val)
+                            val = tmp
+                        else
+                            raise "Could not find group %s" % val
+                        end
+                    else
+                        val
+                    end
                 end
+            end
+            stat = @resource.stat(false)
 
-                return true if gid == current
+            unless stat
+                return :absent
             end
-            return false
-        end
 
-        def retrieve
-            return :absent unless stat = resource.stat(false)
+            # Set our method appropriately, depending on links.
+            if stat.ftype == "link" and @resource[:links] != :follow
+                @method = :lchown
+            else
+                @method = :chown
+            end
 
             currentvalue = stat.gid
 
@@ -79,8 +84,12 @@ module Puppet
 
         # Determine if the group is valid, and if so, return the GID
         def validgroup?(value)
-            if number = gid(value)
-                return number
+            if value =~ /^\d+$/
+                value = value.to_i
+            end
+        
+            if gid = Puppet::Util.gid(value)
+                return gid
             else
                 return false
             end
@@ -90,28 +99,32 @@ module Puppet
         # we'll just let it fail, but we should probably set things up so
         # that users get warned if they try to change to an unacceptable group.
         def sync
-            # Set our method appropriately, depending on links.
-            if resource[:links] == :manage
-                method = :lchown
-            else
-                method = :chown
+            unless @resource.stat(false)
+                stat = @resource.stat(true)
+                currentvalue = self.retrieve
+
+                unless stat
+                    self.debug "File '%s' does not exist; cannot chgrp" %
+                        @resource[:path]
+                    return nil
+                end
             end
 
             gid = nil
-            @should.each do |group|
-                break if gid = validgroup?(group)
+            unless gid = Puppet::Util.gid(self.should)
+                raise Puppet::Error, "Could not find group %s" % self.should
             end
 
-            raise Puppet::Error, "Could not find group(s) %s" % @should.join(",") unless gid
-
             begin
                 # set owner to nil so it's ignored
-                File.send(method, nil, gid, resource[:path])
+                File.send(@method,nil,gid, at resource[:path])
             rescue => detail
-                error = Puppet::Error.new( "failed to chgrp %s to %s: %s" % [resource[:path], gid, detail.message])
+                error = Puppet::Error.new( "failed to chgrp %s to %s: %s" %
+                    [@resource[:path], self.should, detail.message])
                 raise error
             end
             return :file_changed
         end
     end
 end
+
diff --git a/lib/puppet/type/file/selcontext.rb b/lib/puppet/type/file/selcontext.rb
deleted file mode 100644
index d5111ca..0000000
--- a/lib/puppet/type/file/selcontext.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# Manage SELinux context of files.
-#
-# This code actually manages three pieces of data in the context.
-#
-# [root at delenn files]# ls -dZ /
-# drwxr-xr-x  root root system_u:object_r:root_t         /
-#
-# The context of '/' here is 'system_u:object_r:root_t'.  This is
-# three seperate fields:
-#
-# system_u is the user context
-# object_r is the role context
-# root_t is the type context
-#
-# All three of these fields are returned in a single string by the
-# output of the stat command, but set individually with the chcon
-# command.  This allows the user to specify a subset of the three
-# values while leaving the others alone.
-#
-# See http://www.nsa.gov/selinux/ for complete docs on SELinux.
-
-module Puppet
-    require 'puppet/util/selinux'
-
-    class SELFileContext < Puppet::Property
-        include Puppet::Util::SELinux
-
-        def retrieve
-            unless @resource.stat(false)
-                return :absent
-            end
-            context = self.get_selinux_current_context(@resource[:path])
-            return parse_selinux_context(name, context)
-        end
-
-        def retrieve_default_context(property)
-            unless context = self.get_selinux_default_context(@resource[:path])
-                return nil
-            end
-            property_default = self.parse_selinux_context(property, context)
-            self.debug "Found #{property} default '#{property_default}' for #{@resource[:path]}"
-            return property_default
-        end
-
-        def sync
-            unless @resource.stat(false)
-                stat = @resource.stat(true)
-                unless stat
-                    return nil
-                end
-            end
-
-            self.set_selinux_context(@resource[:path], @should, name)
-            return :file_changed
-        end
-    end
-
-    Puppet.type(:file).newproperty(:seluser, :parent => Puppet::SELFileContext) do
-        desc "What the SELinux user component of the context of the file should be.
-            Any valid SELinux user component is accepted.  For example ``user_u``.
-            If not specified it defaults to the value returned by matchpathcon for
-            the file, if any exists.  Only valid on systems with SELinux support
-            enabled."
-
-        @event = :file_changed
-        defaultto { self.retrieve_default_context(:seluser) }
-    end
-
-    Puppet.type(:file).newproperty(:selrole, :parent => Puppet::SELFileContext) do
-        desc "What the SELinux role component of the context of the file should be.
-            Any valid SELinux role component is accepted.  For example ``role_r``.
-            If not specified it defaults to the value returned by matchpathcon for
-            the file, if any exists.  Only valid on systems with SELinux support
-            enabled."
-
-        @event = :file_changed
-        defaultto { self.retrieve_default_context(:selrole) }
-    end
-
-    Puppet.type(:file).newproperty(:seltype, :parent => Puppet::SELFileContext) do
-        desc "What the SELinux type component of the context of the file should be.
-            Any valid SELinux type component is accepted.  For example ``tmp_t``.
-            If not specified it defaults to the value returned by matchpathcon for
-            the file, if any exists.  Only valid on systems with SELinux support
-            enabled."
-
-        @event = :file_changed
-        defaultto { self.retrieve_default_context(:seltype) }
-    end
-
-    Puppet.type(:file).newproperty(:selrange, :parent => Puppet::SELFileContext) do
-        desc "What the SELinux range component of the context of the file should be.
-            Any valid SELinux range component is accepted.  For example ``s0`` or
-            ``SystemHigh``.  If not specified it defaults to the value returned by
-            matchpathcon for the file, if any exists.  Only valid on systems with
-            SELinux support enabled and that have support for MCS (Multi-Category
-            Security)."
-
-        @event = :file_changed
-        defaultto { self.retrieve_default_context(:selrange) }
-    end
-
-end
-
diff --git a/lib/puppet/type/file/source.rb b/lib/puppet/type/file/source.rb
index 2514d3d..1b0dd31 100755
--- a/lib/puppet/type/file/source.rb
+++ b/lib/puppet/type/file/source.rb
@@ -101,7 +101,8 @@ module Puppet
             begin
                 desc = server.describe(path, @resource[:links])
             rescue Puppet::Network::XMLRPCClientError => detail
-                fail detail, "Could not describe %s: %s" % [path, detail]
+                self.err "Could not describe %s: %s" % [path, detail]
+                return nil
             end
 
             return nil if desc == ""
@@ -134,8 +135,18 @@ module Puppet
             return args
         end
         
+        # Have we successfully described the remote source?
+        def described?
+            ! @stats.nil? and ! @stats[:type].nil? #and @is != :notdescribed
+        end
+        
         # Use the info we get from describe() to check if we're in sync.
         def insync?(currentvalue)
+            unless described?
+                warning "No specified sources exist"
+                return true
+            end
+
             if currentvalue == :nocopy
                 return true
             end
@@ -169,11 +180,7 @@ module Puppet
         def pinparams
             [:mode, :type, :owner, :group]
         end
-
-        def found?
-            ! (@stats.nil? or @stats[:type].nil?)
-        end
-
+        
         # This basically calls describe() on our file, and then sets all
         # of the local states appropriately.  If the remote file is a normal
         # file then we set it to copy; if it's a directory, then we just mark
@@ -195,8 +202,8 @@ module Puppet
                 }
             end
 
-            if !found?
-                raise Puppet::Error, "No specified source was found from" + @should.inject("") { |s, source| s + " #{source},"}.gsub(/,$/,"")
+            if @stats.nil? or @stats[:type].nil?
+                return nil # :notdescribed
             end
             
             case @stats[:type]
diff --git a/lib/puppet/type/file/target.rb b/lib/puppet/type/file/target.rb
index 8949c2a..a0e5dc4 100644
--- a/lib/puppet/type/file/target.rb
+++ b/lib/puppet/type/file/target.rb
@@ -54,8 +54,6 @@ module Puppet
         def insync?(currentvalue)
             if [:nochange, :notlink].include?(self.should) or @resource.recurse?
                 return true
-            elsif ! @resource.replace? and File.exists?(@resource[:path])
-                return true 
             else
                 return super(currentvalue)
             end
diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb
index cb11a60..36a4d49 100755
--- a/lib/puppet/type/group.rb
+++ b/lib/puppet/type/group.rb
@@ -110,7 +110,7 @@ module Puppet
             isnamevar
         end
 
-        newparam(:allowdupe, :boolean => true) do
+        newparam(:allowdupe) do
             desc "Whether to allow duplicate GIDs.  This option does not work on
                 FreeBSD (contract to the ``pw`` man page)."
                 
@@ -118,6 +118,14 @@ module Puppet
 
             defaultto false
         end
+
+        def retrieve
+            if self.provider and @provider.exists?
+                return super
+            else
+               return currentpropvalues(:absent) 
+            end
+        end
     end
 end
 
diff --git a/lib/puppet/type/interface.rb b/lib/puppet/type/interface.rb
new file mode 100644
index 0000000..2f6c28a
--- /dev/null
+++ b/lib/puppet/type/interface.rb
@@ -0,0 +1,60 @@
+Puppet::Type.newtype(:interface) do
+	require 'erb'
+
+	@doc = "Create configuration for IP address aliases and loopback addresses."
+
+	newparam(:name, :namevar => true) do
+		desc "The ipaddress to add to alias or loopback/dummy interface"
+	end
+
+    ensurable
+
+	newparam(:interface) do
+		desc "The interface the IP should be added to"
+	end
+
+	newproperty(:interface_type) do
+		desc "The interface type, loopback (also dummy) or alias"
+
+        newvalue(:loopback)
+        newvalue(:alias)
+        newvalue(:normal)
+
+        # Make dummy and loopback equivalent
+        aliasvalue(:dummy, :loopback)
+
+        defaultto :normal
+	end
+
+	newparam(:interface_desc) do
+		desc "On Linux, the description / symbolic name you wish to refer to the 
+              interface by. When absent, Redhat Linux defaults to uses the namevar
+              which will be either the IP address, or hostname."
+	end
+
+	newproperty(:onboot) do
+		desc "Whether the interface should be configured to come up on boot"
+		newvalue(:true)
+		newvalue(:false)
+	end
+
+	newproperty(:ifnum) do
+		desc "If not automatically configuring the dummy interface or
+              and alias. This is use to force a given number to be used"
+	end
+
+	newproperty(:netmask) do
+		desc "The netmask for the interface."
+	end
+
+	newproperty(:ifopts) do
+		desc "Interface options."
+	end
+
+    newparam(:target) do
+        include Puppet::Util::Warnings
+        desc "The path to the file this resource creates."
+
+        munge { |value| warnonce "Interface targets are deprecated and no longer have any function" }
+    end
+end
diff --git a/lib/puppet/type/mount.rb b/lib/puppet/type/mount.rb
index 1679b73..e18630c 100755
--- a/lib/puppet/type/mount.rb
+++ b/lib/puppet/type/mount.rb
@@ -141,9 +141,7 @@ module Puppet
 
         newproperty(:dump) do
             desc "Whether to dump the mount.  Not all platforms
-                support this. Valid values are ``1`` or ``0``. Default is ``0``."
-
-             newvalue(%r{(0|1)}) { }
+                support this."
 
             defaultto {
                 if @resource.managed?
diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb
index 0cea391..f004f7c 100644
--- a/lib/puppet/type/package.rb
+++ b/lib/puppet/type/package.rb
@@ -138,8 +138,8 @@ module Puppet
                             # that can't query versions.
                             return true
                         else
-                            self.debug "%s %s is installed, latest is %s" %
-                                [@resource.name, is.inspect, @latest.inspect]
+                            self.debug "is is %s, latest %s is %s" %
+                                [is.inspect, @resource.name, @latest.inspect]
                         end
                     when :absent
                         return true if is == :absent or is == :purged
diff --git a/lib/puppet/type/selboolean.rb b/lib/puppet/type/selboolean.rb
deleted file mode 100644
index b1f12ca..0000000
--- a/lib/puppet/type/selboolean.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Simple module for manageing SELinux booleans
-#
-
-module Puppet
-    newtype(:selboolean) do
-        @doc = "Manages SELinux booleans on systems with SELinux support.  The supported booleans
-            are any of the ones found in /selinux/booleans/."
-
-        newparam(:name) do
-            desc "The name of the SELinux boolean to be managed."
-            isnamevar
-        end
-
-        newproperty(:value) do
-            desc "Whether the the SELinux boolean should be enabled or disabled."
-            newvalue(:on)
-            newvalue(:off)
-        end
-
-        newparam(:persistent) do
-            desc "If set true, SELinux booleans will be written to disk and persist accross reboots.
-                The default is ``false``."
-
-            defaultto :false
-            newvalues(:true, :false)
-        end
-
-    end
-end
-
diff --git a/lib/puppet/type/selmodule.rb b/lib/puppet/type/selmodule.rb
deleted file mode 100644
index 883cd95..0000000
--- a/lib/puppet/type/selmodule.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# Simple module for manageing SELinux policy modules
-#
-
-Puppet::Type.newtype(:selmodule) do
-    @doc = "Manages loading and unloading of SELinux policy modules
-        on the system.  Requires SELinux support.  See man semodule(8)
-        for more information on SELinux policy modules."
-
-    ensurable
-
-    newparam(:name) do
-        desc "The name of the SELinux policy to be managed.  You should not
-            include the customary trailing .pp extension."
-        isnamevar
-    end
-
-    newparam(:selmoduledir) do
-
-        desc "The directory to look for the compiled pp module file in.
-            Currently defaults to /usr/share/selinux/targeted.  If selmodulepath
-            is not specified the module will be looked for in this directory in a
-            in a file called NAME.pp, where NAME is the value of the name parameter."
-
-        defaultto "/usr/share/selinux/targeted"
-    end
-
-    newparam(:selmodulepath) do
-
-        desc "The full path to the compiled .pp policy module.  You only need to use
-            this if the module file is not in the directory pointed at by selmoduledir."
-
-    end
-
-    newproperty(:syncversion) do
-
-        desc "If set to ``true``, the policy will be reloaded if the
-        version found in the on-disk file differs from the loaded
-        version.  If set to ``false`` (the default) the the only check
-        that will be made is if the policy is loaded at all or not."
-
-        newvalue(:true)
-        newvalue(:false)
-    end
-
-    autorequire(:file) do
-        if self[:selmodulepath]
-            [self[:selmodulepath]]
-        else
-            ["#{self[:selmoduledir]}/#{self[:name]}.pp"]
-        end       
-    end
-end
-
diff --git a/lib/puppet/type/ssh_authorized_key.rb b/lib/puppet/type/ssh_authorized_key.rb
deleted file mode 100644
index 4afca1c..0000000
--- a/lib/puppet/type/ssh_authorized_key.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-module Puppet
-    newtype(:ssh_authorized_key) do
-        @doc = "Manages SSH authorized keys. Currently only type 2 keys are
-        supported."
-
-        ensurable
-
-        newparam(:name) do
-            desc "The SSH key comment."
-
-            isnamevar
-        end
-
-        newproperty(:type) do
-            desc "The encryption type used: ssh-dss or ssh-rsa."
-
-            newvalue("ssh-dss")
-            newvalue("ssh-rsa")
-
-            aliasvalue(:dsa, "ssh-dss")
-            aliasvalue(:rsa, "ssh-rsa")
-        end
-
-        newproperty(:key) do
-            desc "The key itself; generally a long string of hex digits."
-        end
-
-        newproperty(:user) do
-            desc "The user account in which the SSH key should be installed."
-        end
-
-        newproperty(:target) do
-            desc "The file in which to store the SSH key."
-        end
-
-        newproperty(:options, :array_matching => :all) do
-            desc "Key options, see sshd(8) for possible values. Multiple values 
-                  should be specified as an array."
-
-            defaultto do :absent end
-        end
-
-        autorequire(:user) do
-            if should(:user)
-                should(:user)
-            end
-        end
-
-        validate do
-            unless should(:target) or should(:user)
-                raise Puppet::Error, "Attribute 'user' or 'target' is mandatory"
-            end
-        end
-    end
-end
-
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 929e45d..71507d1 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -1,7 +1,5 @@
 require 'etc'
 require 'facter'
-require 'puppet/property/list'
-require 'puppet/property/keyvalue'
 
 module Puppet
     newtype(:user) do
@@ -23,9 +21,6 @@ module Puppet
             "The provider can modify user passwords, by accepting a password
             hash."
 
-        feature :manages_solaris_rbac,
-            "The provider can manage roles and normal users"
-
         newproperty(:ensure, :parent => Puppet::Property::Ensure) do
             newvalue(:present, :event => :user_created) do
                 provider.create
@@ -35,10 +30,6 @@ module Puppet
                 provider.delete
             end
 
-            newvalue(:role, :event => :role_created, :required_features => :manages_solaris_rbac) do
-                provider.create_role
-            end
-
             desc "The basic state that the object should be in."
 
             # If they're talking about the thing at all, they generally want to
@@ -53,15 +44,30 @@ module Puppet
 
             def retrieve
                 if provider.exists?
-                    if provider.respond_to?(:is_role?) and provider.is_role?
-                        return :role
-                    else
-                        return :present
-                    end
+                    return :present
                 else
                     return :absent
                 end
             end
+
+            # The default 'sync' method only selects among a list of registered
+            # values.
+            def sync
+#                if self.insync?
+#                    self.info "already in sync"
+#                    return nil
+                #else
+                    #self.info "%s vs %s" % [self.is.inspect, self.should.inspect]
+#               end
+                unless self.class.values
+                    self.devfail "No values defined for %s" %
+                        self.class.name
+                end
+
+                # Set ourselves to whatever our should value is.
+                self.set(self.should)
+            end
+
         end
 
         newproperty(:uid) do
@@ -89,26 +95,50 @@ module Puppet
         newproperty(:gid) do
             desc "The user's primary group.  Can be specified numerically or
                 by name."
+            
+            def found?
+                defined? @found and @found
+            end
 
-            munge do |value|
-                if value.is_a?(String) and value =~ /^[-0-9]+$/
-                    Integer(value)
+            munge do |gid|
+                method = :getgrgid
+                case gid
+                when String
+                    if gid =~ /^[-0-9]+$/
+                        gid = Integer(gid)
+                    else
+                        method = :getgrnam
+                    end
+                when Symbol
+                    unless gid == :auto or gid == :absent
+                        self.devfail "Invalid GID %s" % gid
+                    end
+                    # these are treated specially by sync()
+                    return gid
+                end
+
+                if group = Puppet::Util.gid(gid)
+                    @found = true
+                    return group
                 else
-                    value
+                    @found = false
+                    return gid
                 end
             end
 
-            def sync
-                found = false
-                @should.each do |value|
-                    if number = Puppet::Util.gid(value)
-                        provider.gid = number
-                        found = true
-                        break
-                    end
+            # *shudder*  Make sure that we've looked up the group and gotten
+            # an ID for it.  Yuck-o.
+            def should
+                unless defined? @should
+                    return super
                 end
-
-                fail "Could not find group(s) %s" % @should.join(",") unless found
+                unless found?
+                    @should = @should.each { |val|
+                        next unless val
+                        Puppet::Util.gid(val)
+                    }
+                end
+                super
             end
         end
 
@@ -128,21 +158,63 @@ module Puppet
 
         newproperty(:password, :required_features => :manages_passwords) do
             desc "The user's password, in whatever encrypted format the local machine requires. Be sure to enclose any value that includes a dollar sign ($) in single quotes (\')."
+        end
+
+        newproperty(:groups) do
+            desc "The groups of which the user is a member.  The primary
+                group should not be listed.  Multiple groups should be
+                specified as an array."
+
+            def should_to_s(newvalue)
+                self.should
+            end
+
+            def is_to_s(currentvalue)
+                currentvalue.join(",")
+            end
 
-            def change_to_s(currentvalue, newvalue)
-                if currentvalue == :absent
-                  return "created password"
+            # We need to override this because the groups need to
+            # be joined with commas
+            def should
+                current_value = retrieve
+
+                unless defined? @should and @should
+                    return nil
+                end
+
+                if @resource[:membership] == :inclusive
+                    return @should.sort.join(",")
                 else
-                  return "changed password"
+                    members = @should
+                    if current_value.is_a?(Array)
+                        members += current_value
+                    end
+                    return members.uniq.sort.join(",")
                 end
             end
-        end
 
+            def retrieve
+                if tmp = provider.groups and tmp != :absent
+                    return tmp.split(",")
+                else
+                    return :absent
+                end
+            end
 
-        newproperty(:groups, :parent => Puppet::Property::List) do
-            desc "The groups of which the user is a member.  The primary
-                group should not be listed.  Multiple groups should be
-                specified as an array."
+            def insync?(is)
+                unless defined? @should and @should
+                    return true
+                end
+                unless defined? is and is
+                    return true
+                end
+                tmp = is
+                if is.is_a? Array
+                    tmp = is.sort.join(",")
+                end
+
+                return tmp == self.should
+            end
 
             validate do |value|
                 if value =~ /^\d+$/
@@ -154,6 +226,29 @@ module Puppet
             end
         end
 
+        # these three properties are all implemented differently on each platform,
+        # so i'm disabling them for now
+
+        # FIXME Puppet::Property::UserLocked is currently non-functional
+        #newproperty(:locked) do
+        #    desc "The expected return code.  An error will be returned if the
+        #        executed command returns something else."
+        #end
+
+        # FIXME Puppet::Property::UserExpire is currently non-functional
+        #newproperty(:expire) do
+        #    desc "The expected return code.  An error will be returned if the
+        #        executed command returns something else."
+        #    @objectaddflag = "-e"
+        #end
+
+        # FIXME Puppet::Property::UserInactive is currently non-functional
+        #newproperty(:inactive) do
+        #    desc "The expected return code.  An error will be returned if the
+        #        executed command returns something else."
+        #    @objectaddflag = "-f"
+        #end
+
         newparam(:name) do
             desc "User name.  While limitations are determined for
                 each operating system, it is generally a good idea to keep to
@@ -165,7 +260,7 @@ module Puppet
             desc "Whether specified groups should be treated as the only groups
                 of which the user is a member or whether they should merely
                 be treated as the minimum membership list."
-
+                
             newvalues(:inclusive, :minimum)
 
             defaultto :minimum
@@ -173,7 +268,7 @@ module Puppet
 
         newparam(:allowdupe, :boolean => true) do
             desc "Whether to allow duplicate UIDs."
-
+                
             newvalues(:true, :false)
 
             defaultto false
@@ -214,7 +309,7 @@ module Puppet
                             gobj.should(:gid) == group
                         }
                             autos << obj
-
+                            
                         end
                     else
                         autos << group
@@ -235,7 +330,7 @@ module Puppet
                 current_value = :absent
 
                 if absent
-                    prophash[property] = :absent
+                   prophash[property] = :absent
                 else
                     current_value = property.retrieve
                     prophash[property] = current_value
@@ -243,122 +338,11 @@ module Puppet
 
                 if property.name == :ensure and current_value == :absent
                     absent = true
+#                    next
                 end
                 prophash
             }
         end
-
-        newproperty(:roles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
-            desc "The roles the user has.  Multiple roles should be
-                specified as an array."
-
-            def membership
-                :role_membership
-            end
-
-            validate do |value|
-                if value =~ /^\d+$/
-                    raise ArgumentError, "Role names must be provided, not numbers"
-                end
-                if value.include?(",")
-                    raise ArgumentError, "Role names must be provided as an array, not a comma-separated list"
-                end
-            end
-        end
-
-        newparam(:role_membership) do
-            desc "Whether specified roles should be treated as the only roles
-                of which the user is a member or whether they should merely
-                be treated as the minimum membership list."
-
-            newvalues(:inclusive, :minimum)
-
-            defaultto :minimum
-        end
-
-        newproperty(:auths, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
-            desc "The auths the user has.  Multiple auths should be
-                specified as an array."
-
-            def membership
-                :auth_membership
-            end
-
-            validate do |value|
-                if value =~ /^\d+$/
-                    raise ArgumentError, "Auth names must be provided, not numbers"
-                end
-                if value.include?(",")
-                    raise ArgumentError, "Auth names must be provided as an array, not a comma-separated list"
-                end
-            end
-        end
-
-        newparam(:auth_membership) do
-            desc "Whether specified auths should be treated as the only auths
-                of which the user is a member or whether they should merely
-                be treated as the minimum membership list."
-
-            newvalues(:inclusive, :minimum)
-
-            defaultto :minimum
-        end
-
-        newproperty(:profiles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
-            desc "The profiles the user has.  Multiple profiles should be
-                specified as an array."
-
-            def membership
-                :profile_membership
-            end
-
-            validate do |value|
-                if value =~ /^\d+$/
-                    raise ArgumentError, "Profile names must be provided, not numbers"
-                end
-                if value.include?(",")
-                    raise ArgumentError, "Profile names must be provided as an array, not a comma-separated list"
-                end
-            end
-        end
-
-        newparam(:profile_membership) do
-            desc "Whether specified roles should be treated as the only roles
-                of which the user is a member or whether they should merely
-                be treated as the minimum membership list."
-
-            newvalues(:inclusive, :minimum)
-
-            defaultto :minimum
-        end
-
-        newproperty(:keys, :parent => Puppet::Property::KeyValue, :required_features => :manages_solaris_rbac) do
-            desc "Specify user attributes in an array of keyvalue pairs"
-
-            def membership
-                :key_membership
-            end
-
-            validate do |value|
-                unless value.include?("=")
-                    raise ArgumentError, "key value pairs must be seperated by an ="
-                end
-            end
-        end
-
-        newparam(:key_membership) do
-            desc "Whether specified key value pairs should be treated as the only attributes
-                of the user or whether they should merely
-                be treated as the minimum list."
-
-            newvalues(:inclusive, :minimum)
-
-            defaultto :minimum
-        end
-
-        newproperty(:project, :required_features => :manages_solaris_rbac) do
-            desc "The name of the project associated with a user"
-        end
     end
 end
 
diff --git a/lib/puppet/type/yumrepo.rb b/lib/puppet/type/yumrepo.rb
index 15e0319..acb3b9b 100644
--- a/lib/puppet/type/yumrepo.rb
+++ b/lib/puppet/type/yumrepo.rb
@@ -1,5 +1,6 @@
 # Description of yum repositories
 
+require 'puppet/propertychange'
 require 'puppet/util/inifile'
 
 module Puppet
@@ -346,23 +347,7 @@ module Puppet
             newvalue(%r{[1-9][0-9]?}) { }
         end
 
-        newproperty(:proxy, :parent => Puppet::IniProperty) do
-            desc "URL to the proxy server for this repository.\n#{ABSENT_DOC}"
-            newvalue(:absent) { self.should = :absent }
-            # Should really check that it's a valid URL
-            newvalue(/.*/) { }
-        end
-
-        newproperty(:proxy_username, :parent => Puppet::IniProperty) do
-            desc "Username for this proxy.\n#{ABSENT_DOC}"
-            newvalue(:absent) { self.should = :absent }
-            newvalue(/.*/) { }
-        end
-
-        newproperty(:proxy_password, :parent => Puppet::IniProperty) do
-            desc "Password for this proxy.\n#{ABSENT_DOC}"
-            newvalue(:absent) { self.should = :absent }
-            newvalue(/.*/) { }
-        end
+        
+        
     end
 end
diff --git a/lib/puppet/type/zone.rb b/lib/puppet/type/zone.rb
index 7601ec4..4fd9267 100644
--- a/lib/puppet/type/zone.rb
+++ b/lib/puppet/type/zone.rb
@@ -377,11 +377,7 @@ end
             result = setstatus(hash)
             result
         else
-            # Return all properties as absent.
-            return properties().inject({}) do | prophash, property|
-                prophash[property] = :absent
-                prophash
-            end
+            return currentpropvalues(:absent)
         end
     end
 
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index 59f732d..560afe1 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -220,18 +220,19 @@ module Util
 
     def binary(bin)
         if bin =~ /^\//
-            if FileTest.file? bin and FileTest.executable? bin
+            if FileTest.exists? bin
                 return bin
             else
                 return nil
             end
         else
-            x = %x{which #{bin} 2>/dev/null}.chomp
-            if x == ""
-                return nil
-            else
-                return x
+            # LAK:NOTE See http://snurl.com/21zf8  [groups_google_com] 
+            x = ENV['PATH'].split(":").each do |dir|
+                if FileTest.exists? File.join(dir, bin)
+                    return File.join(dir, bin)
+                end
             end
+            return nil
         end
     end
     module_function :binary
@@ -312,7 +313,7 @@ module Util
         $VERBOSE = oldverb
         if child_pid
             # Parent process executes this
-            child_status = (Process.waitpid2(child_pid)[1]).to_i >> 8
+            child_status = Process.waitpid2(child_pid)[1]
         else
             # Child process executes this
             Process.setsid
@@ -320,7 +321,6 @@ module Util
                 $stdin.reopen("/dev/null")
                 $stdout.reopen(output_file)
                 $stderr.reopen(output_file)
-                3.upto(256){|fd| IO::new(fd).close rescue nil} 
                 if arguments[:gid]
                     Process.egid = arguments[:gid]
                     Process.gid = arguments[:gid] unless @@os == "Darwin"
diff --git a/lib/puppet/util/filetype.rb b/lib/puppet/util/filetype.rb
index 7e799b6..8dcb672 100755
--- a/lib/puppet/util/filetype.rb
+++ b/lib/puppet/util/filetype.rb
@@ -1,13 +1,8 @@
 # Basic classes for reading, writing, and emptying files.  Not much
 # to see here.
-
-require 'puppet/util/selinux'
-
 class Puppet::Util::FileType
     attr_accessor :loaded, :path, :synced
 
-    include Puppet::Util::SELinux
-
     class << self
         attr_accessor :name
         include Puppet::Util::ClassGen
@@ -114,8 +109,6 @@ class Puppet::Util::FileType
             tf.print text; tf.flush 
             FileUtils.cp(tf.path, @path) 
             tf.close
-            # If SELinux is present, we need to ensure the file has its expected context
-            set_selinux_default_context(@path)
         end
     end
 
diff --git a/lib/puppet/util/ldap.rb b/lib/puppet/util/ldap.rb
deleted file mode 100644
index 33f01f7..0000000
--- a/lib/puppet/util/ldap.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-#  Created by Luke Kanies on 2008-3-23.
-#  Copyright (c) 2008. All rights reserved.
-module Puppet::Util::Ldap
-end
diff --git a/lib/puppet/util/ldap/connection.rb b/lib/puppet/util/ldap/connection.rb
deleted file mode 100644
index 70fe303..0000000
--- a/lib/puppet/util/ldap/connection.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-#  Created by Luke Kanies on 2008-3-23.
-#  Copyright (c) 2008. All rights reserved.
-require 'puppet/util/ldap'
-
-class Puppet::Util::Ldap::Connection
-    attr_accessor :host, :port, :user, :password, :reset, :ssl
-
-    attr_reader :connection
-
-    # Return a default connection, using our default settings.
-    def self.instance
-        ssl = if Puppet[:ldaptls]
-                  :tls
-              elsif Puppet[:ldapssl]
-                  true
-              else
-                  false
-              end
-
-        options = {}
-        options[:ssl] = ssl
-        if user = Puppet.settings[:ldapuser] and user != ""
-            options[:user] = user
-            if pass = Puppet.settings[:ldappassword] and pass != ""
-                options[:password] = pass
-            end
-        end
-
-        new(Puppet[:ldapserver], Puppet[:ldapport], options)
-    end
-
-    def close
-        connection.unbind if connection.bound?
-    end
-
-    def initialize(host, port, options = {})
-        raise Puppet::Error, "Could not set up LDAP Connection: Missing ruby/ldap libraries" unless Puppet.features.ldap?
-
-        @host, @port = host, port
-
-        options.each do |param, value|
-            begin
-                send(param.to_s + "=", value)
-            rescue
-                raise ArgumentError, "LDAP connections do not support %s parameters" % param
-            end
-        end
-    end
-
-    # Create a per-connection unique name.
-    def name
-        [host, port, user, password, ssl].collect { |p| p.to_s }.join("/")
-    end
-
-    # Should we reset the connection?
-    def reset?
-        reset
-    end
-
-    # Start our ldap connection.
-    def start
-        begin
-            case ssl
-            when :tls:
-                @connection = LDAP::SSLConn.new(host, port, true)
-            when true:
-                @connection = LDAP::SSLConn.new(host, port)
-            else
-                @connection = LDAP::Conn.new(host, port)
-            end
-            @connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
-            @connection.set_option(LDAP::LDAP_OPT_REFERRALS, LDAP::LDAP_OPT_ON)
-            @connection.simple_bind(user, password)
-        rescue => detail
-            raise Puppet::Error, "Could not connect to LDAP: %s" % detail
-        end
-    end
-end
diff --git a/lib/puppet/util/ldap/generator.rb b/lib/puppet/util/ldap/generator.rb
deleted file mode 100644
index 2a868b0..0000000
--- a/lib/puppet/util/ldap/generator.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-#  Created by Luke Kanies on 2008-3-28.
-#  Copyright (c) 2008. All rights reserved.
-require 'puppet/util/ldap'
-
-class Puppet::Util::Ldap::Generator
-    # Declare the attribute we'll use to generate the value.
-    def from(source)
-        @source = source
-        return self
-    end
-
-    # Actually do the generation.
-    def generate(value = nil)
-        if value.nil?
-            @generator.call
-        else
-            @generator.call(value)
-        end
-    end
-
-    # Initialize our generator with the name of the parameter
-    # being generated.
-    def initialize(name)
-        @name = name
-    end
-
-    def name
-        @name.to_s
-    end
-
-    def source
-        if defined?(@source) and @source
-            @source.to_s
-        else
-            nil
-        end
-    end
-
-    # Provide the code that does the generation.
-    def with(&block)
-        @generator = block
-        return self
-    end
-end
diff --git a/lib/puppet/util/ldap/manager.rb b/lib/puppet/util/ldap/manager.rb
deleted file mode 100644
index 8d44419..0000000
--- a/lib/puppet/util/ldap/manager.rb
+++ /dev/null
@@ -1,281 +0,0 @@
-require 'puppet/util/ldap'
-require 'puppet/util/ldap/connection'
-require 'puppet/util/ldap/generator'
-
-# The configuration class for LDAP providers, plus
-# connection handling for actually interacting with ldap.
-class Puppet::Util::Ldap::Manager
-    attr_reader :objectclasses, :puppet2ldap, :location, :rdn
-
-    # A null-op that just returns the config.
-    def and
-        return self
-    end
-
-    # Set the offset from the search base and return the config.
-    def at(location)
-        @location = location
-        return self
-    end
-
-    # The basic search base.
-    def base
-        [location, Puppet[:ldapbase]].join(",")
-    end
-
-    # Convert the name to a dn, then pass the args along to
-    # our connection.
-    def create(name, attributes)
-        attributes = attributes.dup
-
-        # Add the objectclasses
-        attributes["objectClass"] = objectclasses.collect { |o| o.to_s }
-        attributes["objectClass"] << "top" unless attributes["objectClass"].include?("top")
-
-        attributes[rdn.to_s] = [name]
-
-        # Generate any new values we might need.
-        generate(attributes)
-
-        # And create our resource.
-        connect { |conn| conn.add dn(name), attributes }
-    end
-
-    # Open, yield, and close the connection.  Cannot be left
-    # open, at this point.
-    def connect
-        raise ArgumentError, "You must pass a block to #connect" unless block_given?
-
-        unless defined?(@connection) and @connection
-            if Puppet[:ldaptls]
-                ssl = :tls
-            elsif Puppet[:ldapssl]
-                ssl = true
-            else
-                ssl = false
-            end
-            options = {:ssl => ssl}
-            if user = Puppet[:ldapuser] and user != ""
-                options[:user] = user
-            end
-            if password = Puppet[:ldappassword] and password != ""
-                options[:password] = password
-            end
-            @connection = Puppet::Util::Ldap::Connection.new(Puppet[:ldapserver], Puppet[:ldapport], options)
-        end
-        @connection.start
-        begin
-            yield @connection.connection
-        ensure
-            @connection.close
-        end
-        return nil
-    end
-
-    # Convert the name to a dn, then pass the args along to
-    # our connection.
-    def delete(name)
-        connect { |connection| connection.delete dn(name) }
-    end
-
-    # Calculate the dn for a given resource.
-    def dn(name)
-        ["%s=%s" % [rdn, name], base].join(",")
-    end
-
-    # Convert an ldap-style entry hash to a provider-style hash.
-    def entry2provider(entry)
-        raise ArgumentError, "Could not get dn from ldap entry" unless entry["dn"]
-
-        # DN is always a single-entry array.  Strip off the bits before the
-        # first comma, then the bits after the remaining equal sign.  This is the
-        # name.
-        name = entry["dn"].dup.pop.split(",").shift.split("=").pop
-
-        result = {:name => name}
-
-        @ldap2puppet.each do |ldap, puppet|
-            result[puppet] = entry[ldap.to_s] || :absent
-        end
-
-        result
-    end
-
-    # Create our normal search filter.
-    def filter
-        return "objectclass=%s" % objectclasses[0] if objectclasses.length == 1
-        return "(&(objectclass=" + objectclasses.join(")(objectclass=") + "))"
-    end
-
-    # Find the associated entry for a resource.  Returns a hash, minus
-    # 'dn', or nil if the entry cannot be found.
-    def find(name)
-        result = nil
-        connect do |conn|
-            begin
-                conn.search2(dn(name), 0, "objectclass=*") do |result|
-                    # Convert to puppet-appropriate attributes
-                    return entry2provider(result)
-                end
-            rescue => detail
-                return nil
-            end
-        end
-    end
-
-    # Declare a new attribute generator.
-    def generates(parameter)
-        @generators << Puppet::Util::Ldap::Generator.new(parameter)
-        @generators[-1]
-    end
-
-    # Generate any extra values we need to make the ldap entry work.
-    def generate(values)
-        return unless @generators.length > 0
-
-        @generators.each do |generator|
-            # Don't override any values that might exist.
-            next if values[generator.name]
-
-            if generator.source
-                unless value = values[generator.source]
-                    raise ArgumentError, "%s must be defined to generate %s" % [generator.source, generator.name]
-                end
-                result = generator.generate(value)
-            else
-                result = generator.generate
-            end
-
-            result = [result] unless result.is_a?(Array)
-            result = result.collect { |r| r.to_s }
-
-            values[generator.name] = result
-        end
-    end
-
-    def initialize
-        @rdn = :cn
-        @generators = []
-    end
-
-    # Specify what classes this provider models.
-    def manages(*classes)
-        @objectclasses = classes
-        return self
-    end
-
-    # Specify the attribute map.  Assumes the keys are the puppet
-    # attributes, and the values are the ldap attributes, and creates a map
-    # for each direction.
-    def maps(attributes)
-        # The map with the puppet attributes as the keys
-        @puppet2ldap = attributes
-
-        # and the ldap attributes as the keys.
-        @ldap2puppet = attributes.inject({}) { |map, ary| map[ary[1]] = ary[0]; map }
-
-        return self
-    end
-
-    # Return the ldap name for a puppet attribute.
-    def ldap_name(attribute)
-        @puppet2ldap[attribute].to_s
-    end
-
-    # Convert the name to a dn, then pass the args along to
-    # our connection.
-    def modify(name, mods)
-        connect { |connection| connection.modify dn(name), mods }
-    end
-
-    # Specify the rdn that we use to build up our dn.
-    def named_by(attribute)
-        @rdn = attribute
-        self
-    end
-
-    # Return the puppet name for an ldap attribute.
-    def puppet_name(attribute)
-        @ldap2puppet[attribute]
-    end
-
-    # Search for all entries at our base.  A potentially expensive search.
-    def search(sfilter = nil)
-        sfilter ||= filter()
-
-        result = []
-        connect do |conn|
-            conn.search2(base, 1, sfilter) do |entry|
-                result << entry2provider(entry)
-            end
-        end
-        return nil if result.empty?
-        return result
-    end
-
-    # Update the ldap entry with the desired state.
-    def update(name, is, should)
-        if should[:ensure] == :absent
-            Puppet.info "Removing %s from ldap" % dn(name)
-            delete(name)
-            return
-        end
-
-        # We're creating a new entry
-        if is.empty? or is[:ensure] == :absent
-            Puppet.info "Creating %s in ldap" % dn(name)
-            # Remove any :absent params and :ensure, then convert the names to ldap names.
-            attrs = ldap_convert(should)
-            create(name, attrs)
-            return
-        end
-
-        # We're modifying an existing entry.  Yuck.
-
-        mods = []
-        # For each attribute we're deleting that is present, create a
-        # modify instance for deletion.
-        [is.keys, should.keys].flatten.uniq.each do |property|
-            # They're equal, so do nothing.
-            next if is[property] == should[property]
-
-            attributes = ldap_convert(should)
-
-            prop_name = ldap_name(property).to_s
-
-            # We're creating it.
-            if is[property] == :absent or is[property].nil?
-                mods << LDAP::Mod.new(LDAP::LDAP_MOD_ADD, prop_name, attributes[prop_name])
-                next
-            end
-
-            # We're deleting it
-            if should[property] == :absent or should[property].nil?
-                mods << LDAP::Mod.new(LDAP::LDAP_MOD_DELETE, prop_name, [])
-                next
-            end
-
-            # We're replacing an existing value
-            mods << LDAP::Mod.new(LDAP::LDAP_MOD_REPLACE, prop_name, attributes[prop_name])
-        end
-
-        modify(name, mods)
-    end
-
-    # Is this a complete ldap configuration?
-    def valid?
-        location and objectclasses and ! objectclasses.empty? and puppet2ldap
-    end
-
-    private
-
-    # Convert a hash of attributes to ldap-like forms.  This mostly means
-    # getting rid of :ensure and making sure everything's an array of strings.
-    def ldap_convert(attributes)
-        attributes.reject { |param, value| value == :absent or param == :ensure }.inject({}) do |result, ary|
-            value = (ary[1].is_a?(Array) ? ary[1] : [ary[1]]).collect { |v| v.to_s }
-            result[ldap_name(ary[0])] = value
-            result
-        end
-    end
-end
diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb
index 0dfd36d..22f4f32 100644
--- a/lib/puppet/util/log.rb
+++ b/lib/puppet/util/log.rb
@@ -1,12 +1,10 @@
 require 'syslog'
-require 'puppet/util/tagging'
 
 # Pass feedback to the user.  Log levels are modeled after syslog's, and it is
 # expected that that will be the most common log destination.  Supports
 # multiple destinations, one of which is a remote server.
 class Puppet::Util::Log
     include Puppet::Util
-    include Puppet::Util::Tagging
 
     @levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit]
     @loglevel = 2
@@ -246,31 +244,23 @@ class Puppet::Util::Log
     newdesttype :console do
                 
         
-        RED 	= {:console => "", :html => "FFA0A0"}
-        GREEN 	= {:console => "", :html => "00CD00"}
-        YELLOW 	= {:console => "", :html => "FFFF60"}
-        BLUE 	= {:console => "", :html => "80A0FF"}
-        PURPLE 	= {:console => "", :html => "FFA500"}
-        CYAN 	= {:console => "", :html => "40FFFF"}
-        WHITE	= {:console => "", :html => "FFFFFF"}
-        HRED	= {:console => "", :html => "FFA0A0"}
-        HGREEN 	= {:console => "", :html => "00CD00"}
-        HYELLOW	= {:console => "", :html => "FFFF60"}
-        HBLUE 	= {:console => "", :html => "80A0FF"}
-        HPURPLE	= {:console => "", :html => "FFA500"}
-        HCYAN 	= {:console => "", :html => "40FFFF"}
-        HWHITE	= {:console => "", :html => "FFFFFF"}
-        RESET 	= {:console => "", :html => ""}
+        PINK = {:console => "", :html => "FFA0A0"}
+        GREEN = {:console => "", :html => "00CD00"}
+        YELLOW = {:console => "", :html => "FFFF60"}
+        SLATE = {:console => "", :html => "80A0FF"}
+        ORANGE = {:console => "", :html => "FFA500"}
+        BLUE = {:console => "", :html => "40FFFF"}
+        RESET = {:console => "", :html => ""}
 
         @@colormap = {
-            :debug => WHITE,
+            :debug => SLATE,
             :info => GREEN,
-            :notice => CYAN,
-            :warning => YELLOW,
-            :err => HPURPLE,
-            :alert => RED,
-            :emerg => HRED,
-            :crit => HRED
+            :notice => PINK,
+            :warning => ORANGE,
+            :err => YELLOW,
+            :alert => BLUE,
+            :emerg => RESET,
+            :crit => RESET
         }
         
         def colorize(level, str)
@@ -472,12 +462,12 @@ class Puppet::Util::Log
         @levels.include?(level)
     end
 
-    attr_accessor :level, :message, :time, :remote
+    attr_accessor :level, :message, :time, :tags, :remote
     attr_reader :source
 
     def initialize(args)
         unless args.include?(:level) && args.include?(:message)
-            raise ArgumentError, "Puppet::Util::Log called incorrectly"
+            raise Puppet::DevError, "Puppet::Util::Log called incorrectly"
         end
 
         if args[:level].class == String
@@ -485,27 +475,35 @@ class Puppet::Util::Log
         elsif args[:level].class == Symbol
             @level = args[:level]
         else
-            raise ArgumentError, "Level is not a string or symbol: #{args[:level].class}"
+            raise Puppet::DevError,
+                "Level is not a string or symbol: #{args[:level].class}"
         end
 
+        # Just return unless we're actually at a level we should send
+        #return unless self.class.sendlevel?(@level)
+
         @message = args[:message].to_s
         @time = Time.now
-
-        raise ArgumentError, "Invalid log level %s" % level unless self.class.validlevel?(level)
-
-        if tags = args[:tags]
-            tags.each { |t| self.tag(t) }
+        # this should include the host name, and probly lots of other
+        # stuff, at some point
+        unless self.class.validlevel?(level)
+            raise Puppet::DevError, "Invalid message level #{level}"
         end
 
-        self.source = args[:source] || "Puppet"
+        if args.include?(:tags)
+            @tags = args[:tags]
+        end
 
-        # Tag myself with my log level
-        tag(level)
+        if args.include?(:source)
+            self.source = args[:source]
+        else
+            @source = "Puppet"
+        end
 
         Log.newmessage(self)
     end
 
-    # Was the source of this log a Puppet resource or parameter?
+    # Was the source of this log an object?
     def objectsource?
         if defined? @objectsource and @objectsource
             @objectsource
@@ -527,11 +525,17 @@ class Puppet::Util::Log
             @objectsource = false
             @source = source.to_s
         end
-        if source.respond_to?(:tags)
-            source.tags.each { |t| tag(t) }
+        unless defined? @tags and @tags
+            if source.respond_to?(:tags)
+                @tags = source.tags
+            end
         end
     end
 
+    def tagged?(tag)
+        @tags.detect { |t| t.to_s == tag.to_s }
+    end
+
     def to_report
         "%s %s (%s): %s" % [self.time, self.source, self.level, self.to_s]
     end
@@ -540,8 +544,5 @@ class Puppet::Util::Log
         return @message
     end
 end
-
-# This is for backward compatibility from when we changed the constant to Puppet::Util::Log
-# because the reports include the constant name.  Apparently the alias was created in
-# March 2007, should could probably be removed soon.
 Puppet::Log = Puppet::Util::Log
+
diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb
index e6d7678..ca23aa8 100644
--- a/lib/puppet/util/metric.rb
+++ b/lib/puppet/util/metric.rb
@@ -5,8 +5,6 @@ require 'puppet'
 class Puppet::Util::Metric
     
     # Load the library as a feature, so we can test its presence.
-    # It's only used by this class, so there's no reason to move it
-    # to the main feature list.
     Puppet.features.add :rrd, :libs => 'RRDtool'
 
     attr_accessor :type, :name, :value, :label
@@ -14,15 +12,6 @@ class Puppet::Util::Metric
 
     attr_writer :basedir
 
-    # Return a specific value
-    def [](name)
-        if value = @values.find { |v| v[0] == name }
-            return value[2]
-        else
-            return nil
-        end
-    end
-
     def basedir
         if defined? @basedir
             @basedir
@@ -104,7 +93,11 @@ class Puppet::Util::Metric
     def initialize(name,label = nil)
         @name = name.to_s
 
-        @label = label || labelize(name)
+        if label
+            @label = label
+        else
+            @label = name.to_s.capitalize.gsub("_", " ")
+        end
 
         @values = []
     end
@@ -114,7 +107,9 @@ class Puppet::Util::Metric
     end
 
     def newvalue(name,value,label = nil)
-        label ||= labelize(name)
+        unless label
+            label = name.to_s.capitalize.gsub("_", " ")
+        end
         @values.push [name,label,value]
     end
 
@@ -150,16 +145,7 @@ class Puppet::Util::Metric
     def values
         @values.sort { |a, b| a[1] <=> b[1] }
     end
-
-    private
-    
-    # Convert a name into a label.
-    def labelize(name)
-        name.to_s.capitalize.gsub("_", " ")
-    end
 end
 
-# This is necessary because we changed the class path in early 2007,
-# and reports directly yaml-dump these metrics, so both client and server
-# have to agree on the class name.
 Puppet::Metric = Puppet::Util::Metric
+
diff --git a/lib/puppet/util/plist.rb b/lib/puppet/util/plist.rb
new file mode 100644
index 0000000..d7a95da
--- /dev/null
+++ b/lib/puppet/util/plist.rb
@@ -0,0 +1,23 @@
+#--
+##############################################################
+# Copyright 2006, Ben Bleything <ben at bleything.net> and      #
+# Patrick May <patrick at hexane.org>                           #
+#                                                            #
+# Distributed under the MIT license.                         #
+##############################################################
+#++
+# = Plist
+#
+# This is the main file for plist.  Everything interesting happens in Plist and Plist::Emit.
+
+require 'base64'
+require 'cgi'
+require 'stringio'
+
+require 'puppet/util/plist/generator'
+require 'puppet/util/plist/parser'
+
+module Plist
+  VERSION = '3.0.0'
+end
+
diff --git a/lib/puppet/util/plist/generator.rb b/lib/puppet/util/plist/generator.rb
new file mode 100644
index 0000000..c615ac4
--- /dev/null
+++ b/lib/puppet/util/plist/generator.rb
@@ -0,0 +1,225 @@
+#--###########################################################
+# Copyright 2006, Ben Bleything <ben at bleything.net> and      #
+# Patrick May <patrick at hexane.org>                           #
+#                                                            #
+# Distributed under the MIT license.                         #
+##############################################################
+#++
+# See Plist::Emit.
+module Plist
+  # === Create a plist
+  # You can dump an object to a plist in one of two ways:
+  #
+  # * <tt>Plist::Emit.dump(obj)</tt>
+  # * <tt>obj.to_plist</tt>
+  #   * This requires that you mixin the <tt>Plist::Emit</tt> module, which is already done for +Array+ and +Hash+.
+  #
+  # The following Ruby classes are converted into native plist types:
+  #   Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
+  # * +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the <array> and <dict> containers (respectively).
+  # * +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a <data> element.
+  # * User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to <tt>Marshal.dump</tt> and the result placed in a <data> element.
+  #
+  # For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below.
+  module Emit
+    # Helper method for injecting into classes.  Calls <tt>Plist::Emit.dump</tt> with +self+.
+    def to_plist(envelope = true)
+      return Plist::Emit.dump(self, envelope)
+    end
+
+    # Helper method for injecting into classes.  Calls <tt>Plist::Emit.save_plist</tt> with +self+.
+    def save_plist(filename)
+      Plist::Emit.save_plist(self, filename)
+    end
+
+    # The following Ruby classes are converted into native plist types:
+    #   Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time
+    #
+    # Write us (via RubyForge) if you think another class can be coerced safely into one of the expected plist classes.
+    #
+    # +IO+ and +StringIO+ objects are encoded and placed in <data> elements; other objects are <tt>Marshal.dump</tt>'ed unless they implement +to_plist_node+.
+    #
+    # The +envelope+ parameters dictates whether or not the resultant plist fragment is wrapped in the normal XML/plist header and footer.  Set it to false if you only want the fragment.
+    def self.dump(obj, envelope = true)
+      output = plist_node(obj)
+
+      output = wrap(output) if envelope
+
+      return output
+    end
+
+    # Writes the serialized object's plist to the specified filename.
+    def self.save_plist(obj, filename)
+      File.open(filename, 'wb') do |f|
+        f.write(obj.to_plist)
+      end
+    end
+
+    private
+    def self.plist_node(element)
+      output = ''
+
+      if element.respond_to? :to_plist_node
+        output << element.to_plist_node
+      else
+        case element
+        when Array
+          if element.empty?
+            output << "<array/>\n"
+          else
+            output << tag('array') {
+              element.collect {|e| plist_node(e)}
+            }
+          end
+        when Hash
+          if element.empty?
+            output << "<dict/>\n"
+          else
+            inner_tags = []
+
+            element.keys.sort.each do |k|
+              v = element[k]
+              inner_tags << tag('key', CGI::escapeHTML(k.to_s))
+              inner_tags << plist_node(v)
+            end
+
+            output << tag('dict') {
+              inner_tags
+            }
+          end
+        when true, false
+          output << "<#{element}/>\n"
+        when Time
+          output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
+        when Date # also catches DateTime
+          output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
+        when String, Symbol, Fixnum, Bignum, Integer, Float
+          output << tag(element_type(element), CGI::escapeHTML(element.to_s))
+        when IO, StringIO
+          element.rewind
+          contents = element.read
+          # note that apple plists are wrapped at a different length then
+          # what ruby's base64 wraps by default.
+          # I used #encode64 instead of #b64encode (which allows a length arg)
+          # because b64encode is b0rked and ignores the length arg.
+          data = "\n"
+          Base64::encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
+          output << tag('data', data)
+        else
+          output << comment( 'The <data> element below contains a Ruby object which has been serialized with Marshal.dump.' )
+          data = "\n"
+          Base64::encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
+          output << tag('data', data )
+        end
+      end
+
+      return output
+    end
+
+    def self.comment(content)
+      return "<!-- #{content} -->\n"
+    end
+
+    def self.tag(type, contents = '', &block)
+      out = nil
+
+      if block_given?
+        out = IndentedString.new
+        out << "<#{type}>"
+        out.raise_indent
+
+        out << block.call
+
+        out.lower_indent
+        out << "</#{type}>"
+      else
+        out = "<#{type}>#{contents.to_s}</#{type}>\n"
+      end
+
+      return out.to_s
+    end
+
+    def self.wrap(contents)
+      output = ''
+
+      output << '<?xml version="1.0" encoding="UTF-8"?>' + "\n"
+      output << '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' + "\n"
+      output << '<plist version="1.0">' + "\n"
+
+      output << contents
+
+      output << '</plist>' + "\n"
+
+      return output
+    end
+
+    def self.element_type(item)
+      return case item
+        when String, Symbol:          'string'
+        when Fixnum, Bignum, Integer: 'integer'
+        when Float:                   'real'
+        else
+          raise "Don't know about this data type... something must be wrong!"
+      end
+    end
+    private
+    class IndentedString #:nodoc:
+      attr_accessor :indent_string
+
+      @@indent_level = 0
+
+      def initialize(str = "\t")
+        @indent_string = str
+        @contents = ''
+      end
+
+      def to_s
+        return @contents
+      end
+
+      def raise_indent
+        @@indent_level += 1
+      end
+
+      def lower_indent
+        @@indent_level -= 1 if @@indent_level > 0
+      end
+
+      def <<(val)
+        if val.is_a? Array
+          val.each do |f|
+            self << f
+          end
+        else
+          # if it's already indented, don't bother indenting further
+          unless val =~ /\A#{@indent_string}/
+            indent = @indent_string * @@indent_level
+
+            @contents << val.gsub(/^/, indent)
+          else
+            @contents << val
+          end
+
+          # it already has a newline, don't add another
+          @contents << "\n" unless val =~ /\n$/
+        end
+      end
+    end
+  end
+end
+
+# we need to add this so sorting hash keys works properly
+class Symbol #:nodoc:
+  def <=> (other)
+    self.to_s <=> other.to_s
+  end
+end
+
+class Array #:nodoc:
+  include Plist::Emit
+end
+
+class Hash #:nodoc:
+  include Plist::Emit
+end
+
diff --git a/lib/puppet/util/plist/parser.rb b/lib/puppet/util/plist/parser.rb
new file mode 100644
index 0000000..7308bfb
--- /dev/null
+++ b/lib/puppet/util/plist/parser.rb
@@ -0,0 +1,226 @@
+#--###########################################################
+# Copyright 2006, Ben Bleything <ben at bleything.net> and      #
+# Patrick May <patrick at hexane.org>                           #
+#                                                            #
+# Distributed under the MIT license.                         #
+##############################################################
+#++
+# Plist parses Mac OS X xml property list files into ruby data structures.
+#
+# === Load a plist file
+# This is the main point of the library:
+#
+#   r = Plist::parse_xml( filename_or_xml )
+module Plist
+# Note that I don't use these two elements much:
+#
+#  + Date elements are returned as DateTime objects.
+#  + Data elements are implemented as Tempfiles
+#
+# Plist::parse_xml will blow up if it encounters a data element.
+# If you encounter such an error, or if you have a Date element which
+# can't be parsed into a Time object, please send your plist file to
+# plist at hexane.org so that I can implement the proper support.
+  def Plist::parse_xml( filename_or_xml )
+    listener = Listener.new
+    #parser = REXML::Parsers::StreamParser.new(File.new(filename), listener)
+    parser = StreamParser.new(filename_or_xml, listener)
+    parser.parse
+    listener.result
+  end
+
+  class Listener
+    #include REXML::StreamListener
+
+    attr_accessor :result, :open
+
+    def initialize
+      @result = nil
+      @open   = Array.new
+    end
+
+
+    def tag_start(name, attributes)
+      @open.push PTag::mappings[name].new
+    end
+
+    def text( contents )
+      @open.last.text = contents if @open.last
+    end
+
+    def tag_end(name)
+      last = @open.pop
+      if @open.empty?
+        @result = last.to_ruby
+      else
+        @open.last.children.push last
+      end
+    end
+  end
+
+  class StreamParser
+    def initialize( filename_or_xml, listener )
+      @filename_or_xml = filename_or_xml
+      @listener = listener
+    end
+
+    TEXT       = /([^<]+)/
+    XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
+    DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
+    COMMENT_START = /\A<!--/u
+    COMMENT_END = /.*?-->/um
+
+
+    def parse
+      plist_tags = PTag::mappings.keys.join('|')
+      start_tag  = /<(#{plist_tags})([^>]*)>/i
+      end_tag    = /<\/(#{plist_tags})[^>]*>/i
+
+      require 'strscan'
+
+      contents = (
+        if (File.exists? @filename_or_xml)
+          File.open(@filename_or_xml) {|f| f.read}
+        else
+          @filename_or_xml
+        end
+      )
+
+      @scanner = StringScanner.new( contents )
+      until @scanner.eos?
+        if @scanner.scan(COMMENT_START)
+          @scanner.scan(COMMENT_END)
+        elsif @scanner.scan(XMLDECL_PATTERN)
+        elsif @scanner.scan(DOCTYPE_PATTERN)
+        elsif @scanner.scan(start_tag)
+          @listener.tag_start(@scanner[1], nil)
+          if (@scanner[2] =~ /\/$/)
+            @listener.tag_end(@scanner[1])
+          end
+        elsif @scanner.scan(TEXT)
+          @listener.text(@scanner[1])
+        elsif @scanner.scan(end_tag)
+          @listener.tag_end(@scanner[1])
+        else
+          raise "Unimplemented element"
+        end
+      end
+    end
+  end
+
+  class PTag
+    @@mappings = { }
+    def PTag::mappings
+      @@mappings
+    end
+
+    def PTag::inherited( sub_class )
+      key = sub_class.to_s.downcase
+      key.gsub!(/^plist::/, '' )
+      key.gsub!(/^p/, '')  unless key == "plist"
+
+      @@mappings[key] = sub_class
+    end
+
+    attr_accessor :text, :children
+    def initialize
+      @children = Array.new
+    end
+
+    def to_ruby
+      raise "Unimplemented: " + self.class.to_s + "#to_ruby on #{self.inspect}"
+    end
+  end
+
+  class PList < PTag
+    def to_ruby
+      children.first.to_ruby if children.first
+    end
+  end
+
+  class PDict < PTag
+    def to_ruby
+      dict = Hash.new
+      key = nil
+
+      children.each do |c|
+        if key.nil?
+          key = c.to_ruby
+        else
+          dict[key] = c.to_ruby
+          key = nil
+        end
+      end
+
+      dict
+    end
+  end
+
+  class PKey < PTag
+    def to_ruby
+      CGI::unescapeHTML(text || '')
+    end
+  end
+
+  class PString < PTag
+    def to_ruby
+      CGI::unescapeHTML(text || '')
+    end
+  end
+
+  class PArray < PTag
+    def to_ruby
+      children.collect do |c|
+        c.to_ruby
+      end
+    end
+  end
+
+  class PInteger < PTag
+    def to_ruby
+      text.to_i
+    end
+  end
+
+  class PTrue < PTag
+    def to_ruby
+      true
+    end
+  end
+
+  class PFalse < PTag
+    def to_ruby
+      false
+    end
+  end
+
+  class PReal < PTag
+    def to_ruby
+      text.to_f
+    end
+  end
+
+  require 'date'
+  class PDate < PTag
+    def to_ruby
+      DateTime.parse(text)
+    end
+  end
+
+  require 'base64'
+  class PData < PTag
+    def to_ruby
+      data = Base64.decode64(text.gsub(/\s+/, ''))
+
+      begin
+        return Marshal.load(data)
+      rescue Exception => e
+        io = StringIO.new
+        io.write data
+        io.rewind
+        return io
+      end
+    end
+  end
+end
+
diff --git a/lib/puppet/util/posix.rb b/lib/puppet/util/posix.rb
index b969a04..cc0340e 100755
--- a/lib/puppet/util/posix.rb
+++ b/lib/puppet/util/posix.rb
@@ -3,20 +3,23 @@ module Puppet::Util::POSIX
 
     # Retrieve a field from a POSIX Etc object.  The id can be either an integer
     # or a name.  This only works for users and groups.  It's also broken on
-    # some platforms, unfortunately, which is why we fall back to the other
-    # method search_posix_field in the gid and uid methods if a sanity check
-    # fails
-    def get_posix_field(space, field, id)
-        raise Puppet::DevError, "Did not get id from caller" unless id
-
+    # some platforms, unfortunately.
+    def old_get_posix_field(space, field, id)
+        unless id
+            raise ArgumentError, "Did not get id"
+        end
+        if id =~ /^\d+$/
+            id = Integer(id)
+        end
+        prefix = "get" + space.to_s
         if id.is_a?(Integer)
             if id > Puppet[:maximum_uid].to_i
                 Puppet.err "Tried to get %s field for silly id %s" % [field, id]
                 return nil
             end
-            method = methodbyid(space)
+            method = (prefix + idfield(space).to_s).intern
         else
-            method = methodbyname(space)
+            method = (prefix + "nam").intern
         end
 
         begin
@@ -28,11 +31,13 @@ module Puppet::Util::POSIX
     end
 
     # A degenerate method of retrieving name/id mappings.  The job of this method is
-    # to retrieve all objects of a certain type, search for a specific entry 
-    # and then return a given field from that entry.
-    def search_posix_field(type, field, id)
+    # to find a specific entry and then return a given field from that entry.
+    def get_posix_field(type, field, id)
         idmethod = idfield(type)
         integer = false
+        if id =~ /^\d+$/
+            id = Integer(id)
+        end
         if id.is_a?(Integer)
             integer = true
             if id > Puppet[:maximum_uid].to_i
@@ -107,70 +112,14 @@ module Puppet::Util::POSIX
         end
     end
     
-    # Determine what the method is to get users and groups by id
-    def methodbyid(space)
-        case Puppet::Util.symbolize(space)
-        when :gr, :group: return :getgrgid
-        when :pw, :user, :passwd: return :getpwuid
-        else
-            raise ArgumentError.new("Can only handle users and groups")
-        end
-    end
-    
-    # Determine what the method is to get users and groups by name
-    def methodbyname(space)
-        case Puppet::Util.symbolize(space)
-        when :gr, :group: return :getgrnam
-        when :pw, :user, :passwd: return :getpwnam
-        else
-            raise ArgumentError.new("Can only handle users and groups")
-        end
-    end
-    
     # Get the GID of a given group, provided either a GID or a name
     def gid(group)
-        begin
-            group = Integer(group)
-        rescue ArgumentError
-            # pass
-        end
-        if group.is_a?(Integer)
-            return nil unless name = get_posix_field(:group, :name, group)
-            gid = get_posix_field(:group, :gid, name)
-            check_value = gid
-        else
-            return nil unless gid = get_posix_field(:group, :gid, group)
-            name = get_posix_field(:group, :name, gid)
-            check_value = name
-        end
-        if check_value != group
-            return search_posix_field(:group, :gid, group)
-        else
-            return gid
-        end
+        get_posix_field(:group, :gid, group)
     end
 
     # Get the UID of a given user, whether a UID or name is provided
     def uid(user)
-        begin
-            user = Integer(user)
-        rescue ArgumentError
-            # pass
-        end
-        if user.is_a?(Integer)
-            return nil unless name = get_posix_field(:passwd, :name, user)
-            uid = get_posix_field(:passwd, :uid, name)
-            check_value = uid
-        else
-            return nil unless uid = get_posix_field(:passwd, :uid, user)
-            name = get_posix_field(:passwd, :name, uid)
-            check_value = name
-        end
-        if check_value != user
-            return search_posix_field(:passwd, :uid, user)
-        else
-            return uid
-        end
+        get_posix_field(:passwd, :uid, user)
     end
 end
 
diff --git a/lib/puppet/util/resource_template.rb b/lib/puppet/util/resource_template.rb
deleted file mode 100644
index 53066a1..0000000
--- a/lib/puppet/util/resource_template.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'puppet/util'
-require 'puppet/util/logging'
-require 'erb'
-
-# A template wrapper that evaluates a template in the
-# context of a resource, allowing the resource attributes
-# to be looked up from within the template.
-#  This provides functionality essentially equivalent to
-# the language's template() function.  You pass your file
-# path and the resource you want to use into the initialization
-# method, then call result() on the instance, and you get back
-# a chunk of text.
-#  The resource's parameters are available as instance variables
-# (as opposed to the language, where we use a method_missing trick).
-#  For example, say you have a resource that generates a file.  You would
-# need to implement the following style of `generate` method:
-#
-#   def generate
-#       template = Puppet::Util::ResourceTemplate.new("/path/to/template", self)
-#
-#       return Puppet::Type.type(:file).create :path => "/my/file",
-#           :content => template.evaluate
-#   end
-#
-# This generated file gets added to the catalog (which is what `generate` does),
-# and its content is the result of the template.  You need to use instance
-# variables in your template, so if your template just needs to have the name
-# of the generating resource, it would just have:
-#
-#   <%= @name %>
-#
-# Since the ResourceTemplate class sets as instance variables all of the resource's
-# parameters.
-#
-# Note that this example uses the generating resource as its source of
-# parameters, which is generally most useful, since it allows you to configure
-# the generated resource via the generating resource.
-class Puppet::Util::ResourceTemplate
-    include Puppet::Util::Logging
-
-    def evaluate
-        set_resource_variables
-        ERB.new(File.read(@file), 0, "-").result(binding)
-    end
-
-    def initialize(file, resource)
-        raise ArgumentError, "Template %s does not exist" % file unless FileTest.exist?(file)
-        @file = file
-        @resource = resource
-    end
-
-    private
-
-    def set_resource_variables
-        @resource.to_hash.each do |param, value|
-            var = "@#{param.to_s}"
-            instance_variable_set(var, value)
-        end
-    end
-end
-
diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb
deleted file mode 100644
index 1487489..0000000
--- a/lib/puppet/util/selinux.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-# Provides utility functions to help interfaces Puppet to SELinux.
-#
-# Currently this is implemented via the command line tools.  At some
-# point support should be added to use the new SELinux ruby bindings
-# as that will be faster and more reliable then shelling out when they
-# are available.  At this time (2008-09-26) these bindings aren't bundled on
-# any SELinux-using distribution I know of.
-
-require 'puppet/util'
-
-module Puppet::Util::SELinux
-
-    include Puppet::Util
-
-    def selinux_support?
-        FileTest.exists?("/selinux/enforce")
-    end
-
-    # Retrieve and return the full context of the file.  If we don't have
-    # SELinux support or if the stat call fails then return nil.
-    def get_selinux_current_context(file)
-        unless selinux_support?
-            return nil
-        end
-        context = ""
-        begin
-            execpipe("/usr/bin/stat -c %C #{file}") do |out|
-                out.each do |line|
-                    context << line
-                end
-            end
-        rescue Puppet::ExecutionFailure
-            return nil
-        end
-        context.chomp!
-        # Handle the case that the system seems to have SELinux support but
-        # stat finds unlabled files.
-        if context == "(null)"
-            return nil
-        end
-        return context
-    end
-
-    # Use the matchpathcon command, if present, to return the SELinux context
-    # which the SELinux policy on the system expects the file to have.  We can
-    # use this to obtain a good default context.  If the command does not
-    # exist or the call fails return nil.
-    #
-    # Note: For this command to work a full, non-relative, filesystem path
-    # should be given.
-    def get_selinux_default_context(file)
-        unless selinux_support?
-            return nil
-        end
-        unless FileTest.executable?("/usr/sbin/matchpathcon")
-            return nil
-        end
-        context = ""
-        begin
-            execpipe("/usr/sbin/matchpathcon #{file}") do |out|
-                out.each do |line|
-                    context << line
-                end
-            end
-        rescue Puppet::ExecutionFailure
-            return nil
-        end
-        # For a successful match, matchpathcon returns two fields separated by
-        # a variable amount of whitespace.  The second field is the full context.
-        context = context.split(/\s/)[1]
-        return context
-    end
-
-    # Take the full SELinux context returned from the tools and parse it
-    # out to the three (or four) component parts.  Supports :seluser, :selrole,
-    # :seltype, and on systems with range support, :selrange.
-    def parse_selinux_context(component, context)
-        if context.nil? or context == "unlabeled"
-            return nil
-        end
-        unless context =~ /^([a-z0-9_]+):([a-z0-9_]+):([a-z0-9_]+)(?::([a-zA-Z0-9:,._-]+))?/
-            raise Puppet::Error, "Invalid context to parse: #{context}"
-        end
-        ret = {
-            :seluser => $1,
-            :selrole => $2,
-            :seltype => $3,
-            :selrange => $4,
-        }
-        return ret[component]
-    end
-
-    # This updates the actual SELinux label on the file.  You can update
-    # only a single component or update the entire context.  It is just a
-    # wrapper around the chcon command.
-    def set_selinux_context(file, value, component = false)
-        unless selinux_support?
-            return nil
-        end
-        case component
-            when :seluser
-                flag = "-u"
-            when :selrole
-                flag = "-r"
-            when :seltype
-                flag = "-t"
-            when :selrange
-                flag = "-l"
-            else
-                flag = nil
-        end
-
-        if flag.nil?
-            cmd = ["/usr/bin/chcon","-h",value,file]
-        else
-            cmd = ["/usr/bin/chcon","-h",flag,value,file]
-        end
-        execute(cmd)
-        return true
-    end
-
-    # Since this call relies on get_selinux_default_context it also needs a
-    # full non-relative path to the file.  Fortunately, that seems to be all
-    # Puppet uses.  This will set the file's SELinux context to the policy's
-    # default context (if any) if it differs from the context currently on
-    # the file.
-    def set_selinux_default_context(file)
-        new_context = get_selinux_default_context(file)
-        unless new_context
-            return nil
-        end
-        cur_context = get_selinux_current_context(file)
-        if new_context != cur_context
-            set_selinux_context(file, new_context)
-            return new_context
-        end
-        return nil
-    end
-end
diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb
index 1e49a3a..d27406d 100644
--- a/lib/puppet/util/settings.rb
+++ b/lib/puppet/util/settings.rb
@@ -114,17 +114,15 @@ class Puppet::Util::Settings
     end
 
     # Do variable interpolation on the value.
-    def convert(value, environment = nil)
+    def convert(value)
         return value unless value
         return value unless value.is_a? String
         newval = value.gsub(/\$(\w+)|\$\{(\w+)\}/) do |value|
             varname = $2 || $1
-            if varname == "environment" and environment
-                environment
-            elsif pval = self.value(varname)
+            if pval = self.value(varname)
                 pval
             else
-                raise Puppet::DevError, "Could not find value for %s" % value
+                raise Puppet::DevError, "Could not find value for %s" % parent
             end
         end
 
@@ -219,64 +217,6 @@ class Puppet::Util::Settings
         @used = []
     end
 
-    # NOTE: ACS ahh the util classes. . .sigh
-    # as part of a fix for 1183, I pulled the logic for the following 5 methods out of the executables and puppet.rb
-    # They probably deserve their own class, but I don't want to do that until I can refactor environments
-    # its a little better than where they were
-
-    # Prints the contents of a config file with the available config elements, or it
-    # prints a single value of a config element.
-    def print_config_options
-        env = value(:environment)
-        val = value(:configprint)
-        if val == "all"
-            hash = {}
-            each do |name, obj|
-                val = value(name,env)
-                val = val.inspect if val == ""
-                hash[name] = val
-            end
-            hash.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, val|
-                puts "%s = %s" % [name, val]
-            end
-        else
-            val.split(/\s*,\s*/).sort.each do |v|
-                if include?(v)
-                    #if there is only one value, just print it for back compatibility
-                    if v == val
-                         puts value(val,env)
-                         break
-                    end
-                    puts "%s = %s" % [v, value(v,env)]
-                else
-                    puts "invalid parameter: %s" % v
-                    return false
-                end
-            end
-        end
-        true
-    end
-
-    def generate_config
-        puts to_config
-        true
-    end
-
-    def generate_manifest
-        puts to_manifest
-        true
-    end
-
-    def print_configs
-        return print_config_options if value(:configprint) != ""
-        return generate_config if value(:genconfig)
-        return generate_manifest if value(:genmanifest)
-    end
-
-    def print_configs?
-        return (value(:configprint) != "" || value(:genconfig) || value(:genmanifest)) && true
-    end
-
     # Return a given object's file metadata.
     def metadata(param)
         if obj = @config[symbolize(param)] and obj.is_a?(CFile)
@@ -647,6 +587,10 @@ These parameters affect the required permissions of any files specified after
 their specification.  Puppet will sometimes use these parameters to check its
 own configured state, so they can be used to make Puppet a bit more self-managing.
 
+Note also that the section names are entirely for human-level organizational
+purposes; they don't provide separate namespaces.  All parameters are in a
+single namespace.
+
 Generated on #{Time.now}.
 
 }.gsub(/^/, "# ")
@@ -729,10 +673,8 @@ Generated on #{Time.now}.
             begin
                 catalog.host_config = false
                 catalog.apply do |transaction|
-                    if transaction.any_failed?
-                        report = transaction.report
-                        failures = report.logs.find_all { |log| log.level == :err }
-                        raise "Got %s failure(s) while initializing: %s" % [failures.length, failures.collect { |l| l.to_s }.join("; ")] 
+                    if failures = transaction.any_failed?
+                        raise "Could not configure for running; got %s failure(s)" % failures
                     end
                 end
             ensure
@@ -783,7 +725,7 @@ Generated on #{Time.now}.
         val = @config[param].default if val.nil?
 
         # Convert it if necessary
-        val = convert(val, environment)
+        val = convert(val)
 
         # And cache it
         @cache[environment||"none"][param] = val
diff --git a/lib/puppet/util/storage.rb b/lib/puppet/util/storage.rb
index dc4e9cd..9358a28 100644
--- a/lib/puppet/util/storage.rb
+++ b/lib/puppet/util/storage.rb
@@ -6,10 +6,6 @@ class Puppet::Util::Storage
     include Singleton
     include Puppet::Util
 
-    def self.state
-        return @@state
-    end
-
     def initialize
         self.class.load
     end
diff --git a/lib/puppet/util/user_attr.rb b/lib/puppet/util/user_attr.rb
deleted file mode 100644
index db8fb81..0000000
--- a/lib/puppet/util/user_attr.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-class UserAttr
-    def self.get_attributes_by_name(name)
-        attributes = nil
-
-        File.readlines('/etc/user_attr').each do |line|
-            next if line =~ /^#/
-
-            token = line.split(':')
-
-            if token[0] == name
-                attributes = {:name => name}
-                token[4].split(';').each do |attr|
-                    key_value = attr.split('=')
-                    attributes[key_value[0].intern] = key_value[1].strip
-                end
-                break
-            end
-        end
-        return attributes
-    end
-end
diff --git a/lib/puppet/util/variables.rb b/lib/puppet/util/variables.rb
new file mode 100644
index 0000000..1a78ef5
--- /dev/null
+++ b/lib/puppet/util/variables.rb
@@ -0,0 +1,38 @@
+module Puppet::Util::Variables
+    def inithooks
+        @instance_init_hooks.dup
+    end
+
+    def initvars
+        return unless defined? @class_init_hooks
+        self.inithooks.each do |var, value|
+            if value.is_a?(Class)
+                instance_variable_set("@" + var.to_s, value.new)
+            else
+                instance_variable_set("@" + var.to_s, value)
+            end
+        end
+    end
+
+    def instancevar(hash)
+        @instance_init_hooks ||= {}
+
+        unless method_defined?(:initvars)
+            define_method(:initvars) do
+                self.class.inithooks.each do |var, value|
+                    if value.is_a?(Class)
+                        instance_variable_set("@" + var.to_s, value.new)
+                    else
+                        instance_variable_set("@" + var.to_s, value)
+                    end
+                end
+            end
+        end
+        hash.each do |var, value|
+            raise("Already initializing %s" % var) if @instance_init_hooks[var]
+
+            @instance_init_hooks[var] = value
+        end
+    end
+end
+
diff --git a/lib/puppet/util/warnings.rb b/lib/puppet/util/warnings.rb
index 97c96b7..d009c39 100644
--- a/lib/puppet/util/warnings.rb
+++ b/lib/puppet/util/warnings.rb
@@ -9,13 +9,6 @@ module Puppet::Util::Warnings
             Puppet.warning msg
             $stampwarnings[self.class] << msg
         end
-
-        return nil
-    end
-
-    def clear_warnings()
-        $stampwarnings = {}
-        return nil
     end
 end
 
diff --git a/man/man8/filebucket.8 b/man/man8/filebucket.8
index 0ef4c38..fdaca9f 100644
--- a/man/man8/filebucket.8
+++ b/man/man8/filebucket.8
@@ -112,5 +112,5 @@ Copyright (c) 2005 Reductive Labs, LLC Licensed under the GNU Public
 License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/pi.8 b/man/man8/pi.8
index ba68579..da13d8e 100644
--- a/man/man8/pi.8
+++ b/man/man8/pi.8
@@ -30,5 +30,5 @@ Only list parameters without detail
 Include metaparams
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/puppet.8 b/man/man8/puppet.8
index 990b7ce..190aab2 100644
--- a/man/man8/puppet.8
+++ b/man/man8/puppet.8
@@ -74,5 +74,5 @@ Copyright (c) 2005 Reductive Labs, LLC Licensed under the GNU Public
 License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/puppet.conf.8 b/man/man8/puppet.conf.8
index 1bc1eb6..e8040fb 100644
--- a/man/man8/puppet.conf.8
+++ b/man/man8/puppet.conf.8
@@ -4,7 +4,7 @@ Configuration Reference \-
 
 .\" Man page generated from reStructeredText.
 This page is autogenerated; any changes will get overwritten 
-.I (last generated on Mon May 05 09:33:01 +1000 2008)
+.I (last generated on Sat Mar 22 17:46:15 +1100 2008)
 
 
 
@@ -691,7 +691,7 @@ puppetmasterd
 
 .TP 2
 \(bu
-Default: production
+Default: development
 
 
 .SS environments
@@ -1739,9 +1739,9 @@ Default: $vardir/yaml
 .ce 0
 .sp
 
-.I This page autogenerated on Mon May 05 09:33:01 +1000 2008
+.I This page autogenerated on Sat Mar 22 17:46:15 +1100 2008
 
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/puppetca.8 b/man/man8/puppetca.8
index f9f89a9..42d6c1f 100644
--- a/man/man8/puppetca.8
+++ b/man/man8/puppetca.8
@@ -42,8 +42,8 @@ configuration options can also be generated by running puppetca with
 
 
 .TP
-.B all:      Operate on all items. Currently only makes sense with
-\'\-\-sign\', \'\-\-clean\', or \'\-\-list\'.
+.B all:      Operate on all outstanding requests. Only makes sense with
+\'\-\-sign\', or \'\-\-list\'.
 
 
 .TP
@@ -51,9 +51,7 @@ configuration options can also be generated by running puppetca with
 This is useful when rebuilding hosts, since new certificate
 signing requests will only be honored if puppetca does not
 have a copy of a signed certificate for that host. The
-certificate of the host remains valid. If \'\-\-all\' is specified
-then all host certificates, both signed and unsigned, will be
-removed.
+certificate of the host remains valid.
 
 debug:    Enable full debugging.
 
@@ -114,5 +112,5 @@ Copyright (c) 2005 Reductive Labs, LLC Licensed under the GNU Public
 License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/puppetd.8 b/man/man8/puppetd.8
index 9cadcd4..83b1728 100644
--- a/man/man8/puppetd.8
+++ b/man/man8/puppetd.8
@@ -180,5 +180,5 @@ Copyright (c) 2005, 2006 Reductive Labs, LLC Licensed under the GNU
 Public License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/puppetdoc.8 b/man/man8/puppetdoc.8
index 8303b7a..d7aacee 100644
--- a/man/man8/puppetdoc.8
+++ b/man/man8/puppetdoc.8
@@ -58,5 +58,5 @@ Copyright (c) 2005\-2007 Reductive Labs, LLC Licensed under the GNU
 Public License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/puppetmasterd.8 b/man/man8/puppetmasterd.8
index c14da72..5a8f027 100644
--- a/man/man8/puppetmasterd.8
+++ b/man/man8/puppetmasterd.8
@@ -83,5 +83,5 @@ Copyright (c) 2005 Reductive Labs, LLC Licensed under the GNU Public
 License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/puppetrun.8 b/man/man8/puppetrun.8
index 6b40481..753be1c 100644
--- a/man/man8/puppetrun.8
+++ b/man/man8/puppetrun.8
@@ -147,5 +147,5 @@ Copyright (c) 2005 Reductive Labs, LLC Licensed under the GNU Public
 License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/man/man8/ralsh.8 b/man/man8/ralsh.8
index 89c99c9..fc84fe0 100644
--- a/man/man8/ralsh.8
+++ b/man/man8/ralsh.8
@@ -111,17 +111,30 @@ luke
 
 .nf
 $ ralsh user luke
-user { \'luke\':
-  home => \'/home/luke\',
-  uid => \'100\',
-  ensure => \'present\',
-  comment => \'Luke Kanies,,,\',
-  gid => \'1000\',
-  shell => \'/bin/bash\',
-  groups => [\'sysadmin\',\'audio\',\'video\',\'puppet\']
-}
 .fi
 
+.\" visit_block_quote
+
+.TP
+.B user { \'luke\':
+home => \'/home/luke\',
+uid => \'100\',
+ensure => \'present\',
+comment => \'Luke Kanies,,,\',
+gid => \'1000\',
+shell => \'/bin/bash\',
+groups => [\'sysadmin\',\'audio\',\'video\',\'puppet\']
+
+\.SH system-message
+System Message: WARNING/2 (./ralsh.rst:, line 87)
+Definition list ends without a blank line; unexpected unindent.
+
+
+}
+
+
+.\" depart_block_quote
+
 .SH AUTHOR
 Luke Kanies
 
@@ -131,5 +144,5 @@ Copyright (c) 2005\-2007 Reductive Labs, LLC Licensed under the GNU
 Public License
 
 
-.\" Generated by docutils manpage writer on 2008-05-05 09:33.
+.\" Generated by docutils manpage writer on 2008-03-22 17:46.
 .\" 
diff --git a/spec/Rakefile b/spec/Rakefile
new file mode 100644
index 0000000..e2996f6
--- /dev/null
+++ b/spec/Rakefile
@@ -0,0 +1,18 @@
+require File.join(File.dirname(__FILE__), "spec_helper.rb")
+require 'rake'
+require 'spec/rake/spectask'
+
+basedir = File.dirname(__FILE__)
+puppetlibdir = File.join(basedir, "../lib")
+puppettestlibdir = File.join(basedir, "../test/lib")
+speclibdir = File.join(basedir, "lib")
+
+libs = [puppetlibdir, puppettestlibdir, speclibdir]
+desc "Run all specs"
+Spec::Rake::SpecTask.new('all') do |t|
+    t.spec_files = FileList['integration/**/*.rb', 'unit/**/*.rb']
+    t.libs = libs
+    t.spec_opts = ['--options', 'spec.opts']
+end
+
+task :default => [:all]
diff --git a/spec/integration/checksum.rb b/spec/integration/checksum.rb
new file mode 100755
index 0000000..c94f3e4
--- /dev/null
+++ b/spec/integration/checksum.rb
@@ -0,0 +1,47 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-22.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/checksum'
+
+describe Puppet::Checksum, " when using the file terminus" do
+    before do
+        Puppet::Checksum.terminus_class = :file
+        @content = "this is some content"
+        @sum = Puppet::Checksum.new(@content)
+
+        @file = Puppet::Checksum.indirection.terminus.path(@sum.checksum)
+    end
+
+    it "should store content at a path determined by its checksum" do
+        File.stubs(:directory?).returns(true)
+        filehandle = mock 'filehandle'
+        filehandle.expects(:print).with(@content)
+        File.expects(:open).with(@file, "w").yields(filehandle)
+
+        @sum.save
+    end
+
+    it "should retrieve stored content when the checksum is provided as the key" do
+        File.stubs(:exist?).returns(true)
+        File.expects(:read).with(@file).returns(@content)
+
+        newsum = Puppet::Checksum.find(@sum.checksum)
+
+        newsum.content.should == @content
+    end
+
+    it "should remove specified files when asked" do
+        File.stubs(:exist?).returns(true)
+        File.expects(:unlink).with(@file)
+
+        Puppet::Checksum.destroy(@sum.name)
+    end
+
+    after do
+        Puppet.settings.clear
+    end
+end
diff --git a/spec/integration/file_serving/configuration.rb b/spec/integration/file_serving/configuration.rb
new file mode 100755
index 0000000..6975594
--- /dev/null
+++ b/spec/integration/file_serving/configuration.rb
@@ -0,0 +1,43 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/configuration'
+
+describe Puppet::FileServing::Configuration, " when finding files with Puppet::FileServing::Mount" do
+    before do
+        # Just in case it already exists.
+        Puppet::FileServing::Configuration.clear_cache
+
+        @mount = Puppet::FileServing::Mount.new("mymount")
+        FileTest.stubs(:exists?).with("/my/path").returns(true)
+        FileTest.stubs(:readable?).with("/my/path").returns(true)
+        FileTest.stubs(:directory?).with("/my/path").returns(true)
+        @mount.path = "/my/path"
+
+        FileTest.stubs(:exists?).with(Puppet[:fileserverconfig]).returns(true)
+        @parser = mock 'parser'
+        @parser.stubs(:parse).returns("mymount" => @mount)
+        @parser.stubs(:changed?).returns(true)
+        Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
+
+        @config = Puppet::FileServing::Configuration.create
+    end
+
+    it "should return nil if the file does not exist" do
+        FileTest.expects(:exists?).with("/my/path/my/file").returns(false)
+        @config.file_path("/mymount/my/file").should be_nil
+    end
+
+    it "should return the full file path if the file exists" do
+        FileTest.expects(:exists?).with("/my/path/my/file").returns(true)
+        @config.file_path("/mymount/my/file").should == "/my/path/my/file"
+    end
+
+    after do
+        Puppet::FileServing::Configuration.clear_cache
+    end
+end
diff --git a/spec/integration/file_serving/content.rb b/spec/integration/file_serving/content.rb
new file mode 100755
index 0000000..aee2a9f
--- /dev/null
+++ b/spec/integration/file_serving/content.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/content'
+require 'shared_behaviours/file_serving'
+
+describe Puppet::FileServing::Content, " when finding files" do
+    it_should_behave_like "Puppet::FileServing::Files"
+
+    before do
+        @test_class = Puppet::FileServing::Content
+        @indirection = Puppet::FileServing::Content.indirection
+    end
+end
diff --git a/spec/integration/file_serving/metadata.rb b/spec/integration/file_serving/metadata.rb
new file mode 100755
index 0000000..5600365
--- /dev/null
+++ b/spec/integration/file_serving/metadata.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/metadata'
+require 'shared_behaviours/file_serving'
+
+describe Puppet::FileServing::Metadata, " when finding files" do
+    it_should_behave_like "Puppet::FileServing::Files"
+
+    before do
+        @test_class = Puppet::FileServing::Metadata
+        @indirection = Puppet::FileServing::Metadata.indirection
+    end
+end
+
diff --git a/spec/integration/indirector/direct_file_server.rb b/spec/integration/indirector/direct_file_server.rb
new file mode 100755
index 0000000..40b753a
--- /dev/null
+++ b/spec/integration/indirector/direct_file_server.rb
@@ -0,0 +1,80 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-19.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/file_content/file'
+require 'puppet/indirector/module_files'
+
+describe Puppet::Indirector::DirectFileServer, " when interacting with the filesystem and the model" do
+    before do
+        # We just test a subclass, since it's close enough.
+        @terminus = Puppet::Indirector::FileContent::File.new
+
+        @filepath = "/path/to/my/file"
+    end
+
+    it "should return an instance of the model" do
+        FileTest.expects(:exists?).with(@filepath).returns(true)
+
+        @terminus.find(@terminus.indirection.request(:find, "file://host#{@filepath}")).should be_instance_of(Puppet::FileServing::Content)
+    end
+
+    it "should return an instance capable of returning its content" do
+        FileTest.expects(:exists?).with(@filepath).returns(true)
+        File.stubs(:lstat).with(@filepath).returns(stub("stat", :ftype => "file"))
+        File.expects(:read).with(@filepath).returns("my content")
+
+        instance = @terminus.find(@terminus.indirection.request(:find, "file://host#{@filepath}"))
+
+        instance.content.should == "my content"
+    end
+end
+
+describe Puppet::Indirector::DirectFileServer, " when interacting with FileServing::Fileset and the model" do
+    before do
+        @terminus = Puppet::Indirector::FileContent::File.new
+
+        @filepath = "/my/file"
+        FileTest.stubs(:exists?).with(@filepath).returns(true)
+
+        stat = stub 'stat', :directory? => true
+        File.stubs(:lstat).with(@filepath).returns(stat)
+
+        @subfiles = %w{one two}
+        @subfiles.each do |f|
+            path = File.join(@filepath, f)
+            FileTest.stubs(:exists?).with(@path).returns(true)
+        end
+
+        Dir.expects(:entries).with(@filepath).returns @subfiles
+
+        @request = @terminus.indirection.request(:search, "file:///my/file", :recurse => true)
+    end
+
+    it "should return an instance for every file in the fileset" do
+        result = @terminus.search(@request)
+        result.should be_instance_of(Array)
+        result.length.should == 3
+        result.each { |r| r.should be_instance_of(Puppet::FileServing::Content) }
+    end
+
+    it "should return instances capable of returning their content" do
+        @subfiles.each do |name|
+            File.stubs(:lstat).with(File.join(@filepath, name)).returns stub("#{name} stat", :ftype => "file", :directory? => false)
+            File.expects(:read).with(File.join(@filepath, name)).returns("#{name} content")
+        end
+
+        @terminus.search(@request).each do |instance|
+            case instance.key
+            when /one/: instance.content.should == "one content"
+            when /two/: instance.content.should == "two content"
+            when /\.$/: 
+            else
+                raise "No valid key for %s" % instance.key.inspect
+            end
+        end
+    end
+end
diff --git a/spec/integration/indirector/file_content/file_server.rb b/spec/integration/indirector/file_content/file_server.rb
new file mode 100755
index 0000000..965bd8f
--- /dev/null
+++ b/spec/integration/indirector/file_content/file_server.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_content/file_server'
+require 'shared_behaviours/file_server_terminus'
+
+describe Puppet::Indirector::FileContent::FileServer, " when finding files" do
+    it_should_behave_like "Puppet::Indirector::FileServerTerminus"
+
+    before do
+        @terminus = Puppet::Indirector::FileContent::FileServer.new
+        @test_class = Puppet::FileServing::Content
+    end
+end
diff --git a/spec/integration/indirector/file_metadata/file_server.rb b/spec/integration/indirector/file_metadata/file_server.rb
new file mode 100755
index 0000000..7caa2e4
--- /dev/null
+++ b/spec/integration/indirector/file_metadata/file_server.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_metadata/file_server'
+require 'shared_behaviours/file_server_terminus'
+
+describe Puppet::Indirector::FileMetadata::FileServer, " when finding files" do
+    it_should_behave_like "Puppet::Indirector::FileServerTerminus"
+
+    before do
+        @terminus = Puppet::Indirector::FileMetadata::FileServer.new
+        @test_class = Puppet::FileServing::Metadata
+    end
+end
diff --git a/spec/integration/indirector/module_files.rb b/spec/integration/indirector/module_files.rb
new file mode 100755
index 0000000..1831bff
--- /dev/null
+++ b/spec/integration/indirector/module_files.rb
@@ -0,0 +1,53 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-19.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/file_content/modules'
+require 'puppet/indirector/module_files'
+
+describe Puppet::Indirector::ModuleFiles, " when interacting with Puppet::Module and FileServing::Content" do
+    it "should look for files in the module's 'files' directory" do
+        Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+        # We just test a subclass, since it's close enough.
+        @terminus = Puppet::Indirector::FileContent::Modules.new
+        @module = Puppet::Module.new("mymod", "/some/path/mymod")
+        Puppet::Module.expects(:find).with("mymod", "myenv").returns(@module)
+
+        filepath = "/some/path/mymod/files/myfile"
+
+        FileTest.expects(:exists?).with(filepath).returns(true)
+
+        @terminus.find("puppetmounts://host/modules/mymod/myfile").should be_instance_of(Puppet::FileServing::Content)
+    end
+end
+
+describe Puppet::Indirector::ModuleFiles, " when interacting with FileServing::Fileset and FileServing::Content" do
+    it "should return an instance for every file in the fileset" do
+        Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+        @terminus = Puppet::Indirector::FileContent::Modules.new
+        @module = Puppet::Module.new("mymod", "/some/path/mymod")
+        Puppet::Module.expects(:find).with("mymod", "myenv").returns(@module)
+
+        filepath = "/some/path/mymod/files/myfile"
+        FileTest.stubs(:exists?).with(filepath).returns(true)
+
+        stat = stub 'stat', :directory? => true
+        File.stubs(:lstat).with(filepath).returns(stat)
+
+        subfiles = %w{one two}
+        subfiles.each do |f|
+            path = File.join(filepath, f)
+            FileTest.stubs(:exists?).with(path).returns(true)
+        end
+
+        Dir.expects(:entries).with(filepath).returns(%w{one two})
+
+        result = @terminus.search("puppetmounts://host/modules/mymod/myfile", :recurse => true)
+        result.should be_instance_of(Array)
+        result.length.should == 3
+        result.each { |r| r.should be_instance_of(Puppet::FileServing::Content) }
+    end
+end
diff --git a/spec/integration/indirector/rest.rb b/spec/integration/indirector/rest.rb
new file mode 100644
index 0000000..cafcce7
--- /dev/null
+++ b/spec/integration/indirector/rest.rb
@@ -0,0 +1,460 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/network/server'
+require 'puppet/indirector'
+require 'puppet/indirector/rest'
+
+# a fake class that will be indirected via REST
+class Puppet::TestIndirectedFoo
+  extend Puppet::Indirector  
+  indirects :test_indirected_foo, :terminus_setting => :test_indirected_foo_terminus
+  
+  attr_reader :value
+  
+  def initialize(value = 0)
+    @value = value
+  end
+  
+  def self.from_yaml(yaml)
+    YAML.load(yaml)
+  end
+  
+  def name
+    "bob"
+  end
+end
+
+# empty Terminus class -- this would normally have to be in a directory findable by the autoloader, but we short-circuit that below
+class Puppet::TestIndirectedFoo::Rest < Puppet::Indirector::REST
+end
+
+
+describe Puppet::Indirector::REST do
+  describe "when using webrick" do
+    before :each do
+      Puppet[:servertype] = 'webrick'
+      @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :test_indirected_foo ] }
+      @server = Puppet::Network::Server.new(@params)
+      @server.listen
+
+      # the autoloader was clearly not written test-first.  We subvert the integration test to get around its bullshit.
+      Puppet::Indirector::Terminus.stubs(:terminus_class).returns(Puppet::TestIndirectedFoo::Rest)
+      Puppet::TestIndirectedFoo.indirection.stubs(:terminus_class).returns :rest
+
+      # Stub the connection information.
+      Puppet::TestIndirectedFoo.indirection.terminus(:rest).stubs(:rest_connection_details).returns(:host => "localhost", :port => 34343)
+    end
+  
+    describe "when finding a model instance over REST" do
+      describe "when a matching model instance can be found" do
+        before :each do
+          @model_instance = Puppet::TestIndirectedFoo.new(23)
+          @mock_model = stub('faked model', :find => @model_instance)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should not fail" do
+          Puppet::TestIndirectedFoo.find('bar')
+          lambda { Puppet::TestIndirectedFoo.find('bar') }.should_not raise_error
+        end
+  
+        it 'should return an instance of the model class' do
+          Puppet::TestIndirectedFoo.find('bar').class.should == Puppet::TestIndirectedFoo
+        end
+  
+        it 'should return the instance of the model class associated with the provided lookup key' do
+          Puppet::TestIndirectedFoo.find('bar').value.should == @model_instance.value
+        end
+  
+        it 'should set an expiration on model instance' do
+          Puppet::TestIndirectedFoo.find('bar').expiration.should_not be_nil
+        end
+      end
+    
+      describe "when no matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :find => nil)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)
+        end
+      
+        it "should return nil" do
+          Puppet::TestIndirectedFoo.find('bar').should be_nil
+        end
+      end
+    
+      describe "when an exception is encountered in looking up a model instance" do
+        before :each do
+          @mock_model = stub('faked model')
+          @mock_model.stubs(:find).raises(RuntimeError)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should raise an exception" do
+          lambda { Puppet::TestIndirectedFoo.find('bar') }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    describe "when searching for model instances over REST" do
+      describe "when matching model instances can be found" do
+        before :each do
+          @model_instances = [ Puppet::TestIndirectedFoo.new(23), Puppet::TestIndirectedFoo.new(24) ]
+          @mock_model = stub('faked model', :search => @model_instances)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should not fail" do
+          lambda { Puppet::TestIndirectedFoo.search('bar') }.should_not raise_error
+        end
+  
+        it 'should return all matching results' do
+          Puppet::TestIndirectedFoo.search('bar').length.should == @model_instances.length
+        end
+  
+        it 'should return model instances' do
+          Puppet::TestIndirectedFoo.search('bar').each do |result| 
+            result.class.should == Puppet::TestIndirectedFoo
+          end
+        end
+  
+        it 'should return the instance of the model class associated with the provided lookup key' do
+          Puppet::TestIndirectedFoo.search('bar').collect(&:value).should == @model_instances.collect(&:value)
+        end
+  
+        it 'should set a version timestamp on model instances' do
+          pending("Luke looking at why this version magic might not be working") do
+            Puppet::TestIndirectedFoo.search('bar').each do |result|
+              result.version.should_not be_nil
+            end
+          end
+        end
+      end
+    
+      describe "when no matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :find => nil)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)
+        end
+      
+        it "should return nil" do
+          Puppet::TestIndirectedFoo.find('bar').should be_nil
+        end
+      end
+    
+      describe "when an exception is encountered in looking up a model instance" do
+        before :each do
+          @mock_model = stub('faked model')
+          @mock_model.stubs(:find).raises(RuntimeError)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should raise an exception" do
+          lambda { Puppet::TestIndirectedFoo.find('bar') }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    describe "when destroying a model instance over REST" do
+      describe "when a matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :destroy => true)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should not fail" do
+          lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should_not raise_error
+        end
+  
+        it 'should return success' do
+          Puppet::TestIndirectedFoo.destroy('bar').should == true
+        end
+      end
+    
+      describe "when no matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :destroy => false)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)
+        end
+      
+        it "should return failure" do
+          Puppet::TestIndirectedFoo.destroy('bar').should == false
+        end
+      end
+    
+      describe "when an exception is encountered in destroying a model instance" do
+        before :each do
+          @mock_model = stub('faked model')
+          @mock_model.stubs(:destroy).raises(RuntimeError)
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should raise an exception" do
+          lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    describe "when saving a model instance over REST" do
+      before :each do
+        @instance = Puppet::TestIndirectedFoo.new(42)
+        @mock_model = stub('faked model', :from_yaml => @instance)
+        Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:model).returns(@mock_model)        
+        Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:save_object).returns(@instance)        
+      end
+      
+      describe "when a successful save can be performed" do
+        before :each do
+        end
+      
+        it "should not fail" do
+          lambda { @instance.save }.should_not raise_error
+        end
+  
+        it 'should return an instance of the model class' do
+          @instance.save.class.should == Puppet::TestIndirectedFoo
+        end
+         
+        it 'should return a matching instance of the model class' do
+          @instance.save.value.should == @instance.value
+        end
+      end
+          
+      describe "when a save cannot be completed" do
+        before :each do
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:save_object).returns(false)
+        end
+              
+        it "should return failure" do
+          @instance.save.should == false
+        end
+      end
+          
+      describe "when an exception is encountered in performing a save" do
+        before :each do
+          Puppet::Network::HTTP::WEBrickREST.any_instance.stubs(:save_object).raises(RuntimeError)       
+        end
+      
+        it "should raise an exception" do
+          lambda { @instance.save }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    after :each do
+      @server.unlisten
+    end
+  end
+
+  describe "when using mongrel" do
+    confine "Mongrel is not available" => Puppet.features.mongrel?
+    
+    before :each do
+      Puppet[:servertype] = 'mongrel'
+      @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :test_indirected_foo ] }
+      @server = Puppet::Network::Server.new(@params)
+      @server.listen
+
+      # the autoloader was clearly not written test-first.  We subvert the integration test to get around its bullshit.
+      Puppet::Indirector::Terminus.stubs(:terminus_class).returns(Puppet::TestIndirectedFoo::Rest)
+      Puppet::TestIndirectedFoo.indirection.stubs(:terminus_class).returns :rest
+
+      # Stub the connection information.
+      Puppet::TestIndirectedFoo.indirection.terminus(:rest).stubs(:rest_connection_details).returns(:host => "localhost", :port => 34343)
+    end
+  
+    describe "when finding a model instance over REST" do
+      describe "when a matching model instance can be found" do
+        before :each do
+          @model_instance = Puppet::TestIndirectedFoo.new(23)
+          @mock_model = stub('faked model', :find => @model_instance)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should not fail" do
+          lambda { Puppet::TestIndirectedFoo.find('bar') }.should_not raise_error
+        end
+  
+        it 'should return an instance of the model class' do
+          Puppet::TestIndirectedFoo.find('bar').class.should == Puppet::TestIndirectedFoo
+        end
+  
+        it 'should return the instance of the model class associated with the provided lookup key' do
+          Puppet::TestIndirectedFoo.find('bar').value.should == @model_instance.value
+        end
+  
+        it 'should set an expiration on model instance' do
+          Puppet::TestIndirectedFoo.find('bar').expiration.should_not be_nil
+        end
+      end
+    
+      describe "when no matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :find => nil)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)
+        end
+      
+        it "should return nil" do
+          Puppet::TestIndirectedFoo.find('bar').should be_nil
+        end
+      end
+    
+      describe "when an exception is encountered in looking up a model instance" do
+        before :each do
+          @mock_model = stub('faked model')
+          @mock_model.stubs(:find).raises(RuntimeError)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should raise an exception" do
+          lambda { Puppet::TestIndirectedFoo.find('bar') }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    describe "when searching for model instances over REST" do
+      describe "when matching model instances can be found" do
+        before :each do
+          @model_instances = [ Puppet::TestIndirectedFoo.new(23), Puppet::TestIndirectedFoo.new(24) ]
+          @mock_model = stub('faked model', :search => @model_instances)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should not fail" do
+          lambda { Puppet::TestIndirectedFoo.search('bar') }.should_not raise_error
+        end
+  
+        it 'should return all matching results' do
+          Puppet::TestIndirectedFoo.search('bar').length.should == @model_instances.length
+        end
+  
+        it 'should return model instances' do
+          Puppet::TestIndirectedFoo.search('bar').each do |result| 
+            result.class.should == Puppet::TestIndirectedFoo
+          end
+        end
+  
+        it 'should return the instance of the model class associated with the provided lookup key' do
+          Puppet::TestIndirectedFoo.search('bar').collect(&:value).should == @model_instances.collect(&:value)
+        end
+  
+        it 'should set an expiration on model instances' do
+          Puppet::TestIndirectedFoo.search('bar').each do |result|
+            result.expiration.should_not be_nil
+          end
+        end
+      end
+    
+      describe "when no matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :find => nil)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)
+        end
+      
+        it "should return nil" do
+          Puppet::TestIndirectedFoo.find('bar').should be_nil
+        end
+      end
+    
+      describe "when an exception is encountered in looking up a model instance" do
+        before :each do
+          @mock_model = stub('faked model')
+          @mock_model.stubs(:find).raises(RuntimeError)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should raise an exception" do
+          lambda { Puppet::TestIndirectedFoo.find('bar') }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    describe "when destroying a model instance over REST" do
+      describe "when a matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :destroy => true)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should not fail" do
+          lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should_not raise_error
+        end
+  
+        it 'should return success' do
+          Puppet::TestIndirectedFoo.destroy('bar').should == true
+        end
+      end
+    
+      describe "when no matching model instance can be found" do
+        before :each do
+          @mock_model = stub('faked model', :destroy => false)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)
+        end
+      
+        it "should return failure" do
+          Puppet::TestIndirectedFoo.destroy('bar').should == false
+        end
+      end
+    
+      describe "when an exception is encountered in destroying a model instance" do
+        before :each do
+          @mock_model = stub('faked model')
+          @mock_model.stubs(:destroy).raises(RuntimeError)
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)        
+        end
+      
+        it "should raise an exception" do
+          lambda { Puppet::TestIndirectedFoo.destroy('bar') }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    describe "when saving a model instance over REST" do
+      before :each do
+        @instance = Puppet::TestIndirectedFoo.new(42)
+        @mock_model = stub('faked model', :from_yaml => @instance)
+        Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:model).returns(@mock_model)        
+        Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:save_object).returns(@instance)        
+      end
+      
+      describe "when a successful save can be performed" do
+        before :each do
+        end
+      
+        it "should not fail" do
+          lambda { @instance.save }.should_not raise_error
+        end
+  
+        it 'should return an instance of the model class' do
+          @instance.save.class.should == Puppet::TestIndirectedFoo
+        end
+         
+        it 'should return a matching instance of the model class' do
+          @instance.save.value.should == @instance.value
+        end
+      end
+          
+      describe "when a save cannot be completed" do
+        before :each do
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:save_object).returns(false)
+        end
+              
+        it "should return failure" do
+          @instance.save.should == false
+        end
+      end
+          
+      describe "when an exception is encountered in performing a save" do
+        before :each do
+          Puppet::Network::HTTP::MongrelREST.any_instance.stubs(:save_object).raises(RuntimeError)       
+        end
+      
+        it "should raise an exception" do
+          lambda { @instance.save }.should raise_error(RuntimeError) 
+        end
+      end
+    end
+
+    after :each do
+      @server.unlisten
+    end
+  end
+end
diff --git a/spec/integration/network/server/mongrel.rb b/spec/integration/network/server/mongrel.rb
new file mode 100644
index 0000000..65caf78
--- /dev/null
+++ b/spec/integration/network/server/mongrel.rb
@@ -0,0 +1,46 @@
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/network/server'
+require 'socket'
+
+describe Puppet::Network::Server do
+  describe "when using mongrel" do
+    confine "Mongrel is not available" => Puppet.features.mongrel?
+    
+    before :each do
+      Puppet[:servertype] = 'mongrel'
+      @params = { :address => "127.0.0.1", :port => 34346, :handlers => [ :node ] }
+      @server = Puppet::Network::Server.new(@params)      
+    end
+
+    describe "before listening" do
+      it "should not be reachable at the specified address and port" do
+        lambda { TCPSocket.new('127.0.0.1', 34346) }.should raise_error(Errno::ECONNREFUSED)
+      end
+    end
+
+    describe "when listening" do
+      it "should be reachable on the specified address and port" do
+        @server.listen
+        lambda { TCPSocket.new('127.0.0.1', 34346) }.should_not raise_error      
+      end
+
+      it "should not allow multiple servers to listen on the same address and port" do
+        @server.listen
+        @server2 = Puppet::Network::Server.new(@params)
+        lambda { @server2.listen }.should raise_error
+      end
+    end
+    
+    describe "after unlistening" do
+      it "should not be reachable on the port and address assigned" do
+        @server.listen
+        @server.unlisten
+        lambda { TCPSocket.new('127.0.0.1', 34346) }.should raise_error(Errno::ECONNREFUSED)        
+      end
+    end
+      
+    after :each do
+      @server.unlisten if @server.listening?
+    end  
+  end
+end
\ No newline at end of file
diff --git a/spec/integration/network/server/webrick.rb b/spec/integration/network/server/webrick.rb
new file mode 100644
index 0000000..0ab8d89
--- /dev/null
+++ b/spec/integration/network/server/webrick.rb
@@ -0,0 +1,46 @@
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/network/server'
+require 'socket'
+
+describe Puppet::Network::Server do
+  describe "when using webrick" do
+    before :each do
+      Puppet[:servertype] = 'webrick'
+      @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :node ] }
+    end
+    
+    describe "before listening" do
+      it "should not be reachable at the specified address and port" do
+        lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error
+      end
+    end
+    
+    describe "when listening" do
+      it "should be reachable on the specified address and port" do
+        @server = Puppet::Network::Server.new(@params.merge(:port => 34343))      
+        @server.listen
+        lambda { TCPSocket.new('127.0.0.1', 34343) }.should_not raise_error      
+      end
+            
+      it "should not allow multiple servers to listen on the same address and port" do
+        @server = Puppet::Network::Server.new(@params.merge(:port => 34343))      
+        @server.listen
+        @server2 = Puppet::Network::Server.new(@params.merge(:port => 34343))
+        lambda { @server2.listen }.should raise_error
+      end
+      
+      after :each do
+        @server.unlisten if @server.listening?
+      end
+    end
+    
+    describe "after unlistening" do
+      it "should not be reachable on the port and address assigned" do
+        @server = Puppet::Network::Server.new(@params.merge(:port => 34343))      
+        @server.listen
+        @server.unlisten
+        lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error(Errno::ECONNREFUSED)        
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/spec/integration/node.rb b/spec/integration/node.rb
new file mode 100755
index 0000000..b0375e7
--- /dev/null
+++ b/spec/integration/node.rb
@@ -0,0 +1,92 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-23.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/node'
+
+describe Puppet::Node do
+    describe "when delegating indirection calls" do
+        before do
+            @name = "me"
+            @node = Puppet::Node.new(@name)
+        end
+
+        it "should be able to use the exec terminus" do
+            Puppet::Node.indirection.stubs(:terminus_class).returns :exec
+
+            # Load now so we can stub
+            terminus = Puppet::Node.indirection.terminus(:exec)
+
+            terminus.expects(:query).with(@name).returns "myresults"
+            terminus.expects(:translate).with(@name, "myresults").returns "translated_results"
+            terminus.expects(:create_node).with(@name, "translated_results").returns @node
+
+            Puppet::Node.find(@name).should equal(@node)
+        end
+
+        it "should be able to use the yaml terminus" do
+            Puppet::Node.indirection.stubs(:terminus_class).returns :yaml
+
+            # Load now, before we stub the exists? method.
+            Puppet::Node.indirection.terminus(:yaml)
+
+            file = File.join(Puppet[:yamldir], "node", "me.yaml")
+            FileTest.expects(:exist?).with(file).returns false
+            Puppet::Node.find(@name).should be_nil
+        end
+
+        it "should have an ldap terminus" do
+            Puppet::Node.indirection.terminus(:ldap).should_not be_nil
+        end
+
+        it "should be able to use the plain terminus" do
+            Puppet::Node.indirection.stubs(:terminus_class).returns :plain
+
+            # Load now, before we stub the exists? method.
+            Puppet::Node.indirection.terminus(:plain)
+
+            Puppet::Node.expects(:new).with(@name).returns @node
+
+            Puppet::Node.find(@name).should equal(@node)
+        end
+
+        describe "and using the memory terminus" do
+            before do
+                @name = "me"
+                @old_terminus = Puppet::Node.indirection.terminus_class
+                @terminus = Puppet::Node.indirection.terminus(:memory)
+                Puppet::Node.indirection.stubs(:terminus).returns @terminus
+                @node = Puppet::Node.new(@name)
+            end
+
+            it "should find no nodes by default" do
+                Puppet::Node.find(@name).should be_nil
+            end
+
+            it "should be able to find nodes that were previously saved" do
+                @node.save
+                Puppet::Node.find(@name).should equal(@node)
+            end
+
+            it "should replace existing saved nodes when a new node with the same name is saved" do
+                @node.save
+                two = Puppet::Node.new(@name)
+                two.save
+                Puppet::Node.find(@name).should equal(two)
+            end
+
+            it "should be able to remove previously saved nodes" do
+                @node.save
+                Puppet::Node.destroy(@node.name)
+                Puppet::Node.find(@name).should be_nil
+            end
+
+            it "should fail when asked to destroy a node that does not exist" do
+                proc { Puppet::Node.destroy(@node) }.should raise_error(ArgumentError)
+            end
+        end
+    end
+end
diff --git a/spec/integration/node/catalog.rb b/spec/integration/node/catalog.rb
new file mode 100755
index 0000000..ca14c2e
--- /dev/null
+++ b/spec/integration/node/catalog.rb
@@ -0,0 +1,38 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-4-8.
+#  Copyright (c) 2008. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Node::Catalog do
+    describe "when using the indirector" do
+        after { Puppet::Node::Catalog.indirection.clear_cache }
+
+        it "should be able to delegate to the :yaml terminus" do
+            Puppet::Node::Catalog.indirection.stubs(:terminus_class).returns :yaml
+
+            # Load now, before we stub the exists? method.
+            Puppet::Node::Catalog.indirection.terminus(:yaml)
+
+            file = File.join(Puppet[:yamldir], "catalog", "me.yaml")
+            FileTest.expects(:exist?).with(file).returns false
+            Puppet::Node::Catalog.find("me").should be_nil
+        end
+
+        it "should be able to delegate to the :compiler terminus" do
+            Puppet::Node::Catalog.indirection.stubs(:terminus_class).returns :compiler
+
+            # Load now, before we stub the exists? method.
+            compiler = Puppet::Node::Catalog.indirection.terminus(:compiler)
+
+            node = mock 'node'
+            node.stub_everything
+
+            Puppet::Node.expects(:find).returns(node)
+            compiler.expects(:compile).with(node).returns nil
+
+            Puppet::Node::Catalog.find("me").should be_nil
+        end
+    end
+end
diff --git a/spec/integration/node/facts.rb b/spec/integration/node/facts.rb
new file mode 100755
index 0000000..c2f8765
--- /dev/null
+++ b/spec/integration/node/facts.rb
@@ -0,0 +1,45 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2008-4-8.
+#  Copyright (c) 2008. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Node::Facts do
+    describe "when using the indirector" do
+        after { Puppet::Node::Facts.indirection.clear_cache }
+
+        it "should expire any cached node instances when it is saved" do
+            Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :yaml
+            terminus = Puppet::Node::Facts.indirection.terminus(:yaml)
+
+            terminus.expects(:save)
+            Puppet::Node.expects(:expire).with("me")
+
+            facts = Puppet::Node::Facts.new("me")
+            facts.save
+        end
+
+        it "should be able to delegate to the :yaml terminus" do
+            Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :yaml
+
+            # Load now, before we stub the exists? method.
+            Puppet::Node::Facts.indirection.terminus(:yaml)
+
+            file = File.join(Puppet[:yamldir], "facts", "me.yaml")
+            FileTest.expects(:exist?).with(file).returns false
+
+            Puppet::Node::Facts.find("me").should be_nil
+        end
+
+        it "should be able to delegate to the :facter terminus" do
+            Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :facter
+
+            Facter.expects(:to_hash).returns "facter_hash"
+            facts = Puppet::Node::Facts.new("me")
+            Puppet::Node::Facts.expects(:new).with("me", "facter_hash").returns facts
+
+            Puppet::Node::Facts.find("me").should equal(facts)
+        end
+    end
+end
diff --git a/spec/integration/ral/types/package.rb b/spec/integration/ral/types/package.rb
new file mode 100755
index 0000000..2056762
--- /dev/null
+++ b/spec/integration/ral/types/package.rb
@@ -0,0 +1,24 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/type/package'
+
+describe Puppet::Type::Package, "when choosing a default package provider" do
+    before do
+        # the default provider is cached.
+        Puppet::Type::Package.defaultprovider = nil
+    end
+
+    def provider_name(os)
+        {"Debian" => :apt, "Darwin" => :apple, "RedHat" => :up2date, "Fedora" => :yum, "FreeBSD" => :ports, "OpenBSD" => :openbsd, "Solaris" => :sun}[os]
+    end
+
+    it "should have a default provider" do
+        Puppet::Type::Package.defaultprovider.should_not be_nil
+    end
+
+    it "should choose the correct provider each platform" do
+        Puppet::Type::Package.defaultprovider.name.should == provider_name(Facter.value(:operatingsystem))
+    end
+end
diff --git a/spec/integration/reports.rb b/spec/integration/reports.rb
new file mode 100755
index 0000000..7351c3d
--- /dev/null
+++ b/spec/integration/reports.rb
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-12.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/reports'
+
+describe Puppet::Reports, " when using report types" do
+    it "should load report types as modules" do
+        Puppet::Reports.report(:store).should be_instance_of(Module)
+    end
+end
diff --git a/spec/integration/transaction/report.rb b/spec/integration/transaction/report.rb
new file mode 100755
index 0000000..48e59f2
--- /dev/null
+++ b/spec/integration/transaction/report.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2008-4-8.
+#  Copyright (c) 2008. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Transaction::Report do
+    describe "when using the indirector" do
+        after { Puppet::Transaction::Report.indirection.clear_cache }
+
+        it "should be able to delegate to the :processor terminus" do
+            Puppet::Transaction::Report.indirection.stubs(:terminus_class).returns :processor
+
+            terminus = Puppet::Transaction::Report.indirection.terminus(:processor)
+
+            Facter.stubs(:value).returns "host.domain.com"
+
+            report = Puppet::Transaction::Report.new
+
+            terminus.expects(:process).with(report)
+
+            report.save
+        end
+    end
+end
diff --git a/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb
new file mode 100644
index 0000000..e2f3d47
--- /dev/null
+++ b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb
@@ -0,0 +1,43 @@
+dir = File.expand_path(File.dirname(__FILE__))
+[ "#{dir}/../../lib", "#{dir}/../../test/lib"].each do |dir|
+    fulldir = File.expand_path(dir)
+    $LOAD_PATH.unshift(fulldir) unless $LOAD_PATH.include?(fulldir)
+end
+
+require 'spec'
+require 'puppettest'
+require 'puppettest/runnable_test'
+
+module Spec
+  module Runner
+    class ExampleGroupRunner
+      def run
+        prepare
+        success = true
+        example_groups.each do |example_group|
+          next unless example_group.runnable?
+          success = success & example_group.run
+        end
+        return success
+      ensure
+        finish
+      end
+    end
+  end
+end
+
+module Spec
+  module Example
+    class ExampleGroup
+      extend PuppetTest::RunnableTest
+    end
+  end
+end
+
+module Test
+  module Unit
+    class TestCase
+      extend PuppetTest::RunnableTest
+    end
+  end
+end
diff --git a/spec/shared_behaviours/file_server_terminus.rb b/spec/shared_behaviours/file_server_terminus.rb
new file mode 100644
index 0000000..de08f29
--- /dev/null
+++ b/spec/shared_behaviours/file_server_terminus.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+describe "Puppet::Indirector::FileServerTerminus", :shared => true do
+    # This only works if the shared behaviour is included before
+    # the 'before' block in the including context.
+    before do
+        Puppet::FileServing::Configuration.clear_cache
+        FileTest.stubs(:exists?).with(Puppet[:fileserverconfig]).returns(true)
+        FileTest.stubs(:exists?).with("/my/mount/path").returns(true)
+        FileTest.stubs(:directory?).with("/my/mount/path").returns(true)
+        FileTest.stubs(:readable?).with("/my/mount/path").returns(true)
+
+        # Use a real mount, so the integration is a bit deeper.
+        @mount1 = Puppet::FileServing::Configuration::Mount.new("one")
+        @mount1.path = "/my/mount/path"
+
+        @parser = stub 'parser', :changed? => false
+        @parser.stubs(:parse).returns("one" => @mount1)
+
+        Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
+
+        # Stub out the modules terminus
+        @modules = mock 'modules terminus'
+    end
+
+    it "should use the file server configuration to find files" do
+        @modules.stubs(:find).returns(nil)
+        @terminus.indirection.stubs(:terminus).with(:modules).returns(@modules)
+
+        path = "/my/mount/path/my/file"
+        FileTest.stubs(:exists?).with(path).returns(true)
+        FileTest.stubs(:exists?).with("/my/mount/path").returns(true)
+        @mount1.expects(:file).with("my/file", :node => nil).returns(path)
+
+        @terminus.find("puppetmounts://myhost/one/my/file").should be_instance_of(@test_class)
+    end
+end
diff --git a/spec/shared_behaviours/file_serving.rb b/spec/shared_behaviours/file_serving.rb
new file mode 100644
index 0000000..82f2072
--- /dev/null
+++ b/spec/shared_behaviours/file_serving.rb
@@ -0,0 +1,54 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+describe "Puppet::FileServing::Files", :shared => true do
+    it "should use the rest terminus when the 'puppet' URI scheme is used and a host name is present" do
+        uri = "puppet://myhost/mymod/my/file"
+        @indirection.terminus(:rest).expects(:find)
+        @test_class.find(uri)
+    end
+
+    it "should use the rest terminus when the 'puppet' URI scheme is used, no host name is present, and the process name is not 'puppet'" do
+        uri = "puppet:///mymod/my/file"
+        Puppet.settings.stubs(:value).with(:name).returns("puppetd")
+        Puppet.settings.stubs(:value).with(:modulepath).returns("")
+        @indirection.terminus(:rest).expects(:find)
+        @test_class.find(uri)
+    end
+
+    it "should use the file_server terminus when the 'puppet' URI scheme is used, no host name is present, and the process name is 'puppet'" do
+        uri = "puppet:///mymod/my/file"
+        Puppet::Node::Environment.stubs(:new).returns(stub("env", :name => "testing"))
+        Puppet.settings.stubs(:value).with(:name).returns("puppet")
+        Puppet.settings.stubs(:value).with(:modulepath, "testing").returns("")
+        Puppet.settings.stubs(:value).with(:modulepath).returns("")
+        Puppet.settings.stubs(:value).with(:libdir).returns("")
+        Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever")
+        Puppet.settings.stubs(:value).with(:environment).returns("")
+        @indirection.terminus(:file_server).expects(:find)
+        @indirection.terminus(:file_server).stubs(:authorized?).returns(true)
+        @test_class.find(uri)
+    end
+
+    it "should use the file_server terminus when the 'puppetmounts' URI scheme is used" do
+        uri = "puppetmounts:///mymod/my/file"
+        @indirection.terminus(:file_server).expects(:find)
+        @indirection.terminus(:file_server).stubs(:authorized?).returns(true)
+        @test_class.find(uri)
+    end
+
+    it "should use the file terminus when the 'file' URI scheme is used" do
+        uri = "file:///mymod/my/file"
+        @indirection.terminus(:file).expects(:find)
+        @test_class.find(uri)
+    end
+
+    it "should use the file terminus when a fully qualified path is provided" do
+        uri = "/mymod/my/file"
+        @indirection.terminus(:file).expects(:find)
+        @test_class.find(uri)
+    end
+end
+
diff --git a/spec/shared_behaviours/memory_terminus.rb b/spec/shared_behaviours/memory_terminus.rb
new file mode 100644
index 0000000..a00dc9f
--- /dev/null
+++ b/spec/shared_behaviours/memory_terminus.rb
@@ -0,0 +1,32 @@
+#
+#  Created by Luke Kanies on 2008-4-8.
+#  Copyright (c) 2008. All rights reserved.
+
+describe "A Memory Terminus", :shared => true do
+    it "should find no instances by default" do
+        @searcher.find(@request).should be_nil
+    end
+
+    it "should be able to find instances that were previously saved" do
+        @searcher.save(@request)
+        @searcher.find(@request).should equal(@instance)
+    end
+
+    it "should replace existing saved instances when a new instance with the same name is saved" do
+        @searcher.save(@request)
+        two = stub 'second', :name => @name
+        trequest = stub 'request', :key => @name, :instance => two
+        @searcher.save(trequest)
+        @searcher.find(@request).should equal(two)
+    end
+
+    it "should be able to remove previously saved instances" do
+        @searcher.save(@request)
+        @searcher.destroy(@request)
+        @searcher.find(@request).should be_nil
+    end
+
+    it "should fail when asked to destroy an instance that does not exist" do
+        proc { @searcher.destroy(@request) }.should raise_error(ArgumentError)
+    end
+end
diff --git a/spec/spec.opts b/spec/spec.opts
new file mode 100644
index 0000000..695852c
--- /dev/null
+++ b/spec/spec.opts
@@ -0,0 +1,5 @@
+--format
+s
+--colour
+--loadby
+mtime
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..db14b47
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,36 @@
+dir = File.expand_path(File.dirname(__FILE__))
+
+$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/**"].each 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'
+require 'spec'
+
+# load any monkey-patches
+Dir["#{dir}/monkey_patches/*.rb"].map { |file| require file }
+
+Spec::Runner.configure do |config|
+  config.mock_with :mocha
+
+#  config.prepend_before :all do
+#      setup_mocks_for_rspec
+#      setup() if respond_to? :setup
+#  end
+#
+#  config.prepend_after :all do
+#      teardown() if respond_to? :teardown
+#  end
+end
diff --git a/spec/unit/file_serving/configuration.rb b/spec/unit/file_serving/configuration.rb
new file mode 100755
index 0000000..a0710e2
--- /dev/null
+++ b/spec/unit/file_serving/configuration.rb
@@ -0,0 +1,224 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/configuration'
+
+describe Puppet::FileServing::Configuration do
+    it "should make :new a private method" do
+        proc { Puppet::FileServing::Configuration.new }.should raise_error
+    end
+
+    it "should return the same configuration each time :create is called" do
+        Puppet::FileServing::Configuration.create.should equal(Puppet::FileServing::Configuration.create)
+    end
+
+    it "should have a method for removing the current configuration instance" do
+        old = Puppet::FileServing::Configuration.create
+        Puppet::FileServing::Configuration.clear_cache
+        Puppet::FileServing::Configuration.create.should_not equal(old)
+    end
+
+    after do
+        Puppet::FileServing::Configuration.clear_cache
+    end
+end
+
+describe Puppet::FileServing::Configuration do
+
+    before :each do
+        @path = "/path/to/configuration/file.conf"
+        Puppet.settings.stubs(:value).with(:fileserverconfig).returns(@path)
+    end
+
+    after :each do
+        Puppet::FileServing::Configuration.clear_cache
+    end
+
+    describe Puppet::FileServing::Configuration, " when initializing" do
+
+        it "should work without a configuration file" do
+            FileTest.stubs(:exists?).with(@path).returns(false)
+            proc { Puppet::FileServing::Configuration.create }.should_not raise_error
+        end
+
+        it "should parse the configuration file if present" do
+            FileTest.stubs(:exists?).with(@path).returns(true)
+            @parser = mock 'parser'
+            @parser.expects(:parse).returns({})
+            Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
+            Puppet::FileServing::Configuration.create
+        end
+
+        it "should determine the path to the configuration file from the Puppet settings" do
+            Puppet::FileServing::Configuration.create
+        end
+    end
+
+    describe Puppet::FileServing::Configuration, " when parsing the configuration file" do
+
+        before do
+            FileTest.stubs(:exists?).with(@path).returns(true)
+            @parser = mock 'parser'
+            Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
+        end
+
+        it "should set the mount list to the results of parsing" do
+            @parser.expects(:parse).returns("one" => mock("mount"))
+            config = Puppet::FileServing::Configuration.create
+            config.mounted?("one").should be_true
+        end
+
+        it "should not raise exceptions" do
+            @parser.expects(:parse).raises(ArgumentError)
+            proc { Puppet::FileServing::Configuration.create }.should_not raise_error
+        end
+
+        it "should replace the existing mount list with the results of reparsing" do
+            @parser.expects(:parse).returns("one" => mock("mount"))
+            config = Puppet::FileServing::Configuration.create
+            config.mounted?("one").should be_true
+            # Now parse again
+            @parser.expects(:parse).returns("two" => mock('other'))
+            config.send(:readconfig, false)
+            config.mounted?("one").should be_false
+            config.mounted?("two").should be_true
+        end
+
+        it "should not replace the mount list until the file is entirely parsed successfully" do
+            @parser.expects(:parse).returns("one" => mock("mount"))
+            @parser.expects(:parse).raises(ArgumentError)
+            config = Puppet::FileServing::Configuration.create
+            # Now parse again, so the exception gets thrown
+            config.send(:readconfig, false)
+            config.mounted?("one").should be_true
+        end
+    end
+
+    describe Puppet::FileServing::Configuration, " when finding files" do
+
+        before do
+            @parser = mock 'parser'
+            @parser.stubs(:changed?).returns true
+            FileTest.stubs(:exists?).with(@path).returns(true)
+            Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
+
+            @mount1 = stub 'mount', :name => "one"
+            @mounts = {"one" => @mount1}
+
+            Facter.stubs(:value).with("hostname").returns("whatever")
+
+            @config = Puppet::FileServing::Configuration.create
+        end
+
+        it "should fail if the uri does not match a leading slash followed by a valid mount name" do
+            @parser.expects(:parse).returns(@mounts)
+            proc { @config.file_path("something") }.should raise_error(ArgumentError)
+        end
+
+        it "should use the first term after the first slash for the mount name" do
+            @parser.expects(:parse).returns(@mounts)
+            FileTest.stubs(:exists?).returns(true)
+            @mount1.expects(:file)
+            @config.file_path("/one")
+        end
+
+        it "should use the remainder of the URI after the mount name as the file name" do
+            @parser.expects(:parse).returns(@mounts)
+            @mount1.expects(:file).with("something/else", {})
+            FileTest.stubs(:exists?).returns(true)
+            @config.file_path("/one/something/else")
+        end
+
+        it "should treat a bare name as a mount and no relative file" do
+            @parser.expects(:parse).returns(@mounts)
+            @mount1.expects(:file).with(nil, {})
+            FileTest.stubs(:exists?).returns(true)
+            @config.file_path("/one")
+        end
+
+        it "should treat a name with a trailing slash equivalently to a name with no trailing slash" do
+            @parser.expects(:parse).returns(@mounts)
+            @mount1.expects(:file).with(nil, {})
+            FileTest.stubs(:exists?).returns(true)
+            @config.file_path("/one/")
+        end
+
+        it "should return nil if the mount cannot be found" do
+            @parser.expects(:changed?).returns(true)
+            @parser.expects(:parse).returns({})
+            @config.file_path("/one/something").should be_nil
+        end
+
+        it "should return nil if the mount does not contain the file" do
+            @parser.expects(:parse).returns(@mounts)
+            @mount1.expects(:file).with("something/else", {}).returns(nil)
+            @config.file_path("/one/something/else").should be_nil
+        end
+
+        it "should return the fully qualified path if the mount exists" do
+            @parser.expects(:parse).returns(@mounts)
+            @mount1.expects(:file).with("something/else", {}).returns("/full/path")
+            @config.file_path("/one/something/else").should == "/full/path"
+        end
+
+        it "should reparse the configuration file when it has changed" do
+            @mount1.stubs(:file).returns("whatever")
+            @parser.expects(:changed?).returns(true)
+            @parser.expects(:parse).returns(@mounts)
+            FileTest.stubs(:exists?).returns(true)
+            @config.file_path("/one/something")
+
+            @parser.expects(:changed?).returns(true)
+            @parser.expects(:parse).returns({})
+            @config.file_path("/one/something").should be_nil
+        end
+    end
+
+    describe Puppet::FileServing::Configuration, " when checking authorization" do
+
+        before do
+            @parser = mock 'parser'
+            @parser.stubs(:changed?).returns true
+            FileTest.stubs(:exists?).with(@path).returns(true)
+            Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
+
+            @mount1 = stub 'mount', :name => "one"
+            @mounts = {"one" => @mount1}
+            @parser.stubs(:parse).returns(@mounts)
+
+            Facter.stubs(:value).with("hostname").returns("whatever")
+
+            @config = Puppet::FileServing::Configuration.create
+        end
+
+        it "should return false if the mount cannot be found" do
+            @config.authorized?("/nope/my/file").should be_false
+        end
+
+        it "should use the mount to determine authorization" do
+            @mount1.expects(:allowed?)
+            @config.authorized?("/one/my/file")
+        end
+
+        it "should pass the client's name to the mount if provided" do
+            @mount1.expects(:allowed?).with("myhost", nil)
+            @config.authorized?("/one/my/file", :node => "myhost")
+        end
+
+        it "should pass the client's IP to the mount if provided" do
+            @mount1.expects(:allowed?).with("myhost", "myip")
+            @config.authorized?("/one/my/file", :node => "myhost", :ipaddress => "myip")
+        end
+
+        it "should return true if the mount allows the client" do
+            @mount1.expects(:allowed?).returns(true)
+            @config.authorized?("/one/my/file").should be_true
+        end
+
+        it "should return false if the mount denies the client"  do
+            @mount1.expects(:allowed?).returns(false)
+            @config.authorized?("/one/my/file").should be_false
+        end
+    end
+end
diff --git a/spec/unit/file_serving/configuration/parser.rb b/spec/unit/file_serving/configuration/parser.rb
new file mode 100755
index 0000000..93d30ca
--- /dev/null
+++ b/spec/unit/file_serving/configuration/parser.rb
@@ -0,0 +1,135 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/file_serving/configuration/parser'
+
+describe Puppet::FileServing::Configuration::Parser do
+    it "should subclass the LoadedFile class" do
+        Puppet::FileServing::Configuration::Parser.superclass.should equal(Puppet::Util::LoadedFile)
+    end
+end
+
+
+module FSConfigurationParserTesting
+    def mock_file_content(content)
+        # We want an array, but we actually want our carriage returns on all of it.
+        lines = content.split("\n").collect { |l| l + "\n" }
+        @filehandle.stubs(:each).multiple_yields(*lines)
+    end
+end
+
+describe Puppet::FileServing::Configuration::Parser do
+    before :each do
+        @path = "/my/config.conf"
+        FileTest.stubs(:exists?).with(@path).returns(true)
+        FileTest.stubs(:readable?).with(@path).returns(true)
+        @filehandle = mock 'filehandle'
+        File.expects(:open).with(@path).yields(@filehandle)
+        @parser = Puppet::FileServing::Configuration::Parser.new(@path)
+    end
+
+    describe Puppet::FileServing::Configuration::Parser, " when parsing" do
+        include FSConfigurationParserTesting
+
+        before do
+            @parser.stubs(:add_modules_mount)
+        end
+
+        it "should allow comments" do
+            @filehandle.expects(:each).yields("# this is a comment\n")
+            proc { @parser.parse }.should_not raise_error
+        end
+
+        it "should allow blank lines" do
+            @filehandle.expects(:each).yields("\n")
+            proc { @parser.parse }.should_not raise_error
+        end
+
+        it "should create a new mount for each section in the configuration" do
+            mount1 = mock 'one'
+            mount2 = mock 'two'
+            Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1)
+            Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2)
+            mock_file_content "[one]\n[two]\n"
+            @parser.parse
+        end
+
+        # This test is almost the exact same as the previous one.
+        it "should return a hash of the created mounts" do
+            mount1 = mock 'one'
+            mount2 = mock 'two'
+            Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1)
+            Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2)
+            mock_file_content "[one]\n[two]\n"
+
+            @parser.parse.should == {"one" => mount1, "two" => mount2}
+        end
+
+        it "should only allow mount names that are alphanumeric plus dashes" do
+            mock_file_content "[a*b]\n"
+            proc { @parser.parse }.should raise_error(ArgumentError)
+        end
+
+        it "should fail if the value for path/allow/deny starts with an equals sign" do
+            mock_file_content "[one]\npath = /testing"
+            proc { @parser.parse }.should raise_error(ArgumentError)
+        end
+    end
+
+    describe Puppet::FileServing::Configuration::Parser, " when parsing mount attributes" do
+        include FSConfigurationParserTesting
+
+        before do
+            @mount = stub 'mount', :name => "one"
+            Puppet::FileServing::Mount.expects(:new).with("one").returns(@mount)
+            @parser.stubs(:add_modules_mount)
+        end
+
+        it "should set the mount path to the path attribute from that section" do
+            mock_file_content "[one]\npath /some/path\n"
+
+            @mount.expects(:path=).with("/some/path")
+            @parser.parse
+        end
+
+        it "should tell the mount to allow any allow values from the section" do
+            mock_file_content "[one]\nallow something\n"
+
+            @mount.expects(:info)
+            @mount.expects(:allow).with("something")
+            @parser.parse
+        end
+
+        it "should tell the mount to deny any deny values from the section" do
+            mock_file_content "[one]\ndeny something\n"
+
+            @mount.expects(:info)
+            @mount.expects(:deny).with("something")
+            @parser.parse
+        end
+
+        it "should fail on any attributes other than path, allow, and deny" do
+            mock_file_content "[one]\ndo something\n"
+
+            proc { @parser.parse }.should raise_error(ArgumentError)
+        end
+    end
+
+    describe Puppet::FileServing::Configuration::Parser, " when parsing the modules mount" do
+        include FSConfigurationParserTesting
+
+        before do
+            @mount = stub 'mount', :name => "modules"
+            Puppet::FileServing::Mount.expects(:new).with("modules").returns(@mount)
+        end
+
+        it "should warn if a path is set" do
+            mock_file_content "[modules]\npath /some/path\n"
+
+            @modules.expects(:path=).never
+            Puppet.expects(:warning)
+            @parser.parse
+        end
+    end
+end
diff --git a/spec/unit/file_serving/content.rb b/spec/unit/file_serving/content.rb
new file mode 100755
index 0000000..89d7862
--- /dev/null
+++ b/spec/unit/file_serving/content.rb
@@ -0,0 +1,71 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/content'
+
+describe Puppet::FileServing::Content do
+    it "should should be a subclass of FileBase" do
+        Puppet::FileServing::Content.superclass.should equal(Puppet::FileServing::FileBase)
+    end
+
+    it "should indirect file_content" do
+        Puppet::FileServing::Content.indirection.name.should == :file_content
+    end
+
+    it "should should include the IndirectionHooks module in its indirection" do
+        Puppet::FileServing::Content.indirection.metaclass.included_modules.should include(Puppet::FileServing::IndirectionHooks)
+    end
+end
+
+describe Puppet::FileServing::Content, " when returning the contents" do
+    before do
+        @path = "/my/base"
+        @content = Puppet::FileServing::Content.new("sub/path", :links => :follow, :path => @path)
+    end
+
+    it "should fail if the file is a symlink and links are set to :manage" do
+        @content.links = :manage
+        File.expects(:lstat).with(@path).returns stub("stat", :ftype => "symlink")
+        proc { @content.content }.should raise_error(ArgumentError)
+    end
+
+    it "should fail if a path is not set" do
+        proc { @content.content() }.should raise_error(Errno::ENOENT)
+    end
+
+    it "should raise Errno::ENOENT if the file is absent" do
+        @content.path = "/there/is/absolutely/no/chance/that/this/path/exists"
+        proc { @content.content() }.should raise_error(Errno::ENOENT)
+    end
+
+    it "should return the contents of the path if the file exists" do
+        File.expects(:stat).with(@path).returns stub("stat", :ftype => "file")
+        File.expects(:read).with(@path).returns(:mycontent)
+        @content.content.should == :mycontent
+    end
+end
+
+describe Puppet::FileServing::Content, " when converting to yaml" do
+    it "should fail if no path has been set" do
+        @content = Puppet::FileServing::Content.new("some/key")
+        proc { @content.to_yaml }.should raise_error(ArgumentError)
+    end
+
+    it "should return the file contents" do
+        @content = Puppet::FileServing::Content.new("some/path")
+        @content.path = "/base/path"
+        @content.expects(:content).returns(:content)
+        @content.to_yaml.should == :content
+    end
+end
+
+describe Puppet::FileServing::Content, " when converting from yaml" do
+    # LAK:FIXME This isn't in the right place, but we need some kind of
+    # control somewhere that requires that all REST connections only pull
+    # from the file-server, thus guaranteeing they go through our authorization
+    # hook.
+    it "should set the URI scheme to 'puppetmounts'" do
+        pending "We need to figure out where this should be"
+    end
+end
diff --git a/spec/unit/file_serving/file_base.rb b/spec/unit/file_serving/file_base.rb
new file mode 100755
index 0000000..ded6ae4
--- /dev/null
+++ b/spec/unit/file_serving/file_base.rb
@@ -0,0 +1,124 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/file_base'
+
+describe Puppet::FileServing::FileBase do
+    it "should accept a key in the form of a URI" do
+        Puppet::FileServing::FileBase.new("puppet://host/module/dir/file").key.should == "puppet://host/module/dir/file"
+    end
+
+    it "should allow specification of whether links should be managed" do
+        Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :links => :manage).links.should == :manage
+    end
+
+    it "should consider :ignore links equivalent to :manage links" do
+        Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :links => :ignore).links.should == :manage
+    end
+
+    it "should fail if :links is set to anything other than :manage, :follow, or :ignore" do
+        proc { Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :links => :else) }.should raise_error(ArgumentError)
+    end
+
+    it "should default to :manage for :links" do
+        Puppet::FileServing::FileBase.new("puppet://host/module/dir/file").links.should == :manage
+    end
+
+    it "should allow specification of a path" do
+        FileTest.stubs(:exists?).returns(true)
+        Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :path => "/my/file").path.should == "/my/file"
+    end
+
+    it "should allow specification of a relative path" do
+        FileTest.stubs(:exists?).returns(true)
+        Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :relative_path => "my/file").relative_path.should == "my/file"
+    end
+
+    it "should have a means of determining if the file exists" do
+        Puppet::FileServing::FileBase.new("blah").should respond_to(:exist?)
+    end
+
+    it "should correctly indicate if the file is present" do
+        File.expects(:lstat).with("/my/file").returns(mock("stat"))
+        Puppet::FileServing::FileBase.new("blah", :path => "/my/file").exist?.should be_true
+    end
+
+    it "should correctly indicate if the file is asbsent" do
+        File.expects(:lstat).with("/my/file").raises RuntimeError
+        Puppet::FileServing::FileBase.new("blah", :path => "/my/file").exist?.should be_false
+    end
+
+    describe "when setting the base path" do
+        before do
+            @file = Puppet::FileServing::FileBase.new("puppet://host/module/dir/file")
+        end
+
+        it "should require that the base path be fully qualified" do
+            FileTest.stubs(:exists?).returns(true)
+            proc { @file.path = "unqualified/file" }.should raise_error(ArgumentError)
+        end
+    end
+
+    describe "when setting the relative path" do
+        it "should require that the relative path be unqualified" do
+            @file = Puppet::FileServing::FileBase.new("puppet://host/module/dir/file")
+            FileTest.stubs(:exists?).returns(true)
+            proc { @file.relative_path = "/qualified/file" }.should raise_error(ArgumentError)
+        end
+    end
+
+    describe "when determining the full file path" do
+        before do
+            @file = Puppet::FileServing::FileBase.new("mykey", :path => "/this/file")
+        end
+
+        it "should return the path if there is no relative path" do
+            @file.full_path.should == "/this/file"
+        end
+
+        it "should return the path if the relative_path is set to ''" do
+            @file.relative_path = ""
+            @file.full_path.should == "/this/file"
+        end
+
+        it "should return the path joined with the relative path if there is a relative path and it is not set to '/' or ''" do
+            @file.relative_path = "not/qualified"
+            @file.full_path.should == "/this/file/not/qualified"
+        end
+
+        it "should should fail if there is no path set" do
+            @file = Puppet::FileServing::FileBase.new("not/qualified")
+            proc { @file.full_path }.should raise_error(ArgumentError)
+        end
+    end
+
+    describe "when stat'ing files" do
+        before do
+            @file = Puppet::FileServing::FileBase.new("mykey", :path => "/this/file")
+        end
+
+        it "should stat the file's full path" do
+            @file.stubs(:full_path).returns("/this/file")
+            File.expects(:lstat).with("/this/file").returns stub("stat", :ftype => "file")
+            @file.stat
+        end
+
+        it "should fail if the file does not exist" do
+            @file.stubs(:full_path).returns("/this/file")
+            File.expects(:lstat).with("/this/file").raises(Errno::ENOENT)
+            proc { @file.stat }.should raise_error(Errno::ENOENT)
+        end
+
+        it "should use :lstat if :links is set to :manage" do
+            File.expects(:lstat).with("/this/file").returns stub("stat", :ftype => "file")
+            @file.stat
+        end
+
+        it "should use :stat if :links is set to :follow" do
+            File.expects(:stat).with("/this/file").returns stub("stat", :ftype => "file")
+            @file.links = :follow
+            @file.stat
+        end
+    end
+end
diff --git a/spec/unit/file_serving/fileset.rb b/spec/unit/file_serving/fileset.rb
new file mode 100755
index 0000000..2cd3e83
--- /dev/null
+++ b/spec/unit/file_serving/fileset.rb
@@ -0,0 +1,230 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/fileset'
+
+describe Puppet::FileServing::Fileset, " when initializing" do
+    it "should require a path" do
+        proc { Puppet::FileServing::Fileset.new }.should raise_error(ArgumentError)
+    end
+
+    it "should fail if its path is not fully qualified" do
+        proc { Puppet::FileServing::Fileset.new("some/file") }.should raise_error(ArgumentError)
+    end
+
+    it "should fail if its path does not exist" do
+        File.expects(:lstat).with("/some/file").returns nil
+        proc { Puppet::FileServing::Fileset.new("/some/file") }.should raise_error(ArgumentError)
+    end
+
+    it "should accept a 'recurse' option" do
+        File.expects(:lstat).with("/some/file").returns stub("stat")
+        set = Puppet::FileServing::Fileset.new("/some/file", :recurse => true)
+        set.recurse.should be_true
+    end
+
+    it "should accept an 'ignore' option" do
+        File.expects(:lstat).with("/some/file").returns stub("stat")
+        set = Puppet::FileServing::Fileset.new("/some/file", :ignore => ".svn")
+        set.ignore.should == [".svn"]
+    end
+
+    it "should accept a 'links' option" do
+        File.expects(:lstat).with("/some/file").returns stub("stat")
+        set = Puppet::FileServing::Fileset.new("/some/file", :links => :manage)
+        set.links.should == :manage
+    end
+
+    it "should fail if 'links' is set to anything other than :manage or :follow" do
+        proc { Puppet::FileServing::Fileset.new("/some/file", :links => :whatever) }.should raise_error(ArgumentError)
+    end
+
+    it "should default to 'false' for recurse" do
+        File.expects(:lstat).with("/some/file").returns stub("stat")
+        Puppet::FileServing::Fileset.new("/some/file").recurse.should == false
+    end
+
+    it "should default to an empty ignore list" do
+        File.expects(:lstat).with("/some/file").returns stub("stat")
+        Puppet::FileServing::Fileset.new("/some/file").ignore.should == []
+    end
+
+    it "should default to :manage for links" do
+        File.expects(:lstat).with("/some/file").returns stub("stat")
+        Puppet::FileServing::Fileset.new("/some/file").links.should == :manage
+    end
+end
+
+describe Puppet::FileServing::Fileset, " when determining whether to recurse" do
+    before do
+        @path = "/my/path"
+        File.expects(:lstat).with(@path).returns stub("stat")
+        @fileset = Puppet::FileServing::Fileset.new(@path)
+    end
+
+    it "should always recurse if :recurse is set to 'true'" do
+        @fileset.recurse = true
+        @fileset.recurse?(0).should be_true
+    end
+
+    it "should never recurse if :recurse is set to 'false'" do
+        @fileset.recurse = false
+        @fileset.recurse?(-1).should be_false
+    end
+
+    it "should recurse if :recurse is set to an integer and the current depth is less than that integer" do
+        @fileset.recurse = 1
+        @fileset.recurse?(0).should be_true
+    end
+
+    it "should recurse if :recurse is set to an integer and the current depth is equal to that integer" do
+        @fileset.recurse = 1
+        @fileset.recurse?(1).should be_true
+    end
+
+    it "should not recurse if :recurse is set to an integer and the current depth is greater than that integer" do
+        @fileset.recurse = 1
+        @fileset.recurse?(2).should be_false
+    end
+
+    it "should not recurse if :recurse is set to 0" do
+        @fileset.recurse = 0
+        @fileset.recurse?(-1).should be_false
+    end
+end
+
+describe Puppet::FileServing::Fileset, " when recursing" do
+    before do
+        @path = "/my/path"
+        File.expects(:lstat).with(@path).returns stub("stat", :directory? => true)
+        @fileset = Puppet::FileServing::Fileset.new(@path)
+
+        @dirstat = stub 'dirstat', :directory? => true
+        @filestat = stub 'filestat', :directory? => false
+    end
+
+    def mock_dir_structure(path, stat_method = :lstat)
+        File.stubs(stat_method).with(path).returns(@dirstat)
+        Dir.stubs(:entries).with(path).returns(%w{one two .svn CVS})
+
+        # Keep track of the files we're stubbing.
+        @files = %w{.}
+
+        %w{one two .svn CVS}.each do |subdir|
+            @files << subdir # relative path
+            subpath = File.join(path, subdir)
+            File.stubs(stat_method).with(subpath).returns(@dirstat)
+            Dir.stubs(:entries).with(subpath).returns(%w{.svn CVS file1 file2})
+            %w{file1 file2 .svn CVS}.each do |file|
+                @files << File.join(subdir, file) # relative path
+                File.stubs(stat_method).with(File.join(subpath, file)).returns(@filestat)
+            end
+        end
+    end
+
+    it "should recurse through the whole file tree if :recurse is set to 'true'" do
+        mock_dir_structure(@path)
+        @fileset.stubs(:recurse?).returns(true)
+        @fileset.files.sort.should == @files.sort
+    end
+
+    it "should not recurse if :recurse is set to 'false'" do
+        mock_dir_structure(@path)
+        @fileset.stubs(:recurse?).returns(false)
+        @fileset.files.should == %w{.}
+    end
+
+    # It seems like I should stub :recurse? here, or that I shouldn't stub the
+    # examples above, but...
+    it "should recurse to the level set if :recurse is set to an integer" do
+        mock_dir_structure(@path)
+        @fileset.recurse = 1
+        @fileset.files.should == %w{. one two .svn CVS}
+    end
+
+    it "should ignore the '.' and '..' directories in subdirectories" do
+        mock_dir_structure(@path)
+        @fileset.recurse = true
+        @fileset.files.sort.should == @files.sort
+    end
+
+    it "should ignore files that match a single pattern in the ignore list" do
+        mock_dir_structure(@path)
+        @fileset.recurse = true
+        @fileset.ignore = ".svn"
+        @fileset.files.find { |file| file.include?(".svn") }.should be_nil
+    end
+
+    it "should ignore files that match any of multiple patterns in the ignore list" do
+        mock_dir_structure(@path)
+        @fileset.recurse = true
+        @fileset.ignore = %w{.svn CVS}
+        @fileset.files.find { |file| file.include?(".svn") or file.include?("CVS") }.should be_nil
+    end
+
+    it "should use File.stat if :links is set to :follow" do
+        mock_dir_structure(@path, :stat)
+        @fileset.recurse = true
+        @fileset.links = :follow
+        @fileset.files.sort.should == @files.sort
+    end
+
+    it "should use File.lstat if :links is set to :manage" do
+        mock_dir_structure(@path, :lstat)
+        @fileset.recurse = true
+        @fileset.links = :manage
+        @fileset.files.sort.should == @files.sort
+    end
+end
+
+describe Puppet::FileServing::Fileset, " when following links that point to missing files" do
+    before do
+        @path = "/my/path"
+        File.expects(:lstat).with(@path).returns stub("stat", :directory? => true)
+        @fileset = Puppet::FileServing::Fileset.new(@path)
+        @fileset.links = :follow
+        @fileset.recurse = true
+
+        @stat = stub 'stat', :directory? => true
+
+        File.expects(:stat).with(@path).returns(@stat)
+        File.expects(:stat).with(File.join(@path, "mylink")).raises(Errno::ENOENT)
+        Dir.stubs(:entries).with(@path).returns(["mylink"])
+    end
+
+    it "should not fail" do
+        proc { @fileset.files }.should_not raise_error
+    end
+
+    it "should still manage the link" do
+        @fileset.files.sort.should == %w{. mylink}.sort
+    end
+end
+
+describe Puppet::FileServing::Fileset, " when ignoring" do
+    before do
+        @path = "/my/path"
+        File.expects(:lstat).with(@path).returns stub("stat", :directory? => true)
+        @fileset = Puppet::FileServing::Fileset.new(@path)
+    end
+
+    it "should use ruby's globbing to determine what files should be ignored" do
+        @fileset.ignore = ".svn"
+        File.expects(:fnmatch?).with(".svn", "my_file")
+        @fileset.ignore?("my_file")
+    end
+
+    it "should ignore files whose paths match a single provided ignore value" do
+        @fileset.ignore = ".svn"
+        File.stubs(:fnmatch?).with(".svn", "my_file").returns true
+        @fileset.ignore?("my_file").should be_true
+    end
+
+    it "should ignore files whose paths match any of multiple provided ignore values" do
+        @fileset.ignore = [".svn", "CVS"]
+        File.stubs(:fnmatch?).with(".svn", "my_file").returns false
+        File.stubs(:fnmatch?).with("CVS", "my_file").returns true
+        @fileset.ignore?("my_file").should be_true
+    end
+end
diff --git a/spec/unit/file_serving/indirection_hooks.rb b/spec/unit/file_serving/indirection_hooks.rb
new file mode 100755
index 0000000..160e3ff
--- /dev/null
+++ b/spec/unit/file_serving/indirection_hooks.rb
@@ -0,0 +1,124 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/indirection_hooks'
+
+describe Puppet::FileServing::IndirectionHooks do
+    before do
+        @object = Object.new
+        @object.extend(Puppet::FileServing::IndirectionHooks)
+
+        @request = stub 'request', :key => "http://myhost/blah", :options => {:node => "whatever"}
+    end
+
+    describe "when being used to select termini" do
+        it "should escape the key before parsing" do
+            uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something"
+            URI.expects(:escape).with("http://myhost/blah").returns("escaped_blah")
+            URI.expects(:parse).with("escaped_blah").returns(uri)
+            @object.select_terminus(@request)
+        end
+
+        it "should use the URI class to parse the key" do
+            uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something"
+            URI.expects(:parse).with("http://myhost/blah").returns(uri)
+            @object.select_terminus @request
+        end
+
+        it "should choose :rest when the protocol is 'puppet'" do
+            @request.stubs(:key).returns "puppet://host/module/file"
+            @object.select_terminus(@request).should == :rest
+        end
+
+        it "should choose :file_server when the protocol is 'puppetmounts' and the mount name is not 'modules'" do
+            modules = mock 'modules'
+            @object.stubs(:terminus).with(:modules).returns(modules)
+            modules.stubs(:find_module).returns(nil)
+
+            @request.stubs(:key).returns "puppetmounts://host/notmodules/file"
+
+            @object.select_terminus(@request).should == :file_server
+        end
+
+        it "should choose :file_server when no server name is provided, the process name is 'puppet', and the mount name is not 'modules'" do
+            modules = mock 'modules'
+            @object.stubs(:terminus).with(:modules).returns(modules)
+            modules.stubs(:find_module).returns(nil)
+
+            Puppet.settings.expects(:value).with(:name).returns("puppet")
+            @request.stubs(:key).returns "puppet:///notmodules/file"
+            @object.select_terminus(@request).should == :file_server
+        end
+
+        it "should choose :modules if it would normally choose :file_server but the mount name is 'modules'" do
+            @request.stubs(:key).returns "puppetmounts://host/modules/mymod/file"
+            @object.select_terminus(@request).should == :modules
+        end
+
+        it "should choose :modules if it would normally choose :file_server but a module exists with the mount name" do
+            modules = mock 'modules'
+
+            @object.expects(:terminus).with(:modules).returns(modules)
+            modules.expects(:find_module).with("mymod", @request.options[:node]).returns(:thing)
+
+            @request.stubs(:key).returns "puppetmounts://host/mymod/file"
+            @object.select_terminus(@request).should == :modules
+        end
+
+        it "should choose :rest when no server name is provided and the process name is not 'puppet'" do
+            Puppet.settings.expects(:value).with(:name).returns("puppetd")
+            @request.stubs(:key).returns "puppet:///module/file"
+            @object.select_terminus(@request).should == :rest
+        end
+
+        it "should choose :file when the protocol is 'file'" do
+            @request.stubs(:key).returns "file://host/module/file"
+            @object.select_terminus(@request).should == :file
+        end
+
+        it "should choose :file when the URI is a normal path name" do
+            @request.stubs(:key).returns "/module/file"
+            @object.select_terminus(@request).should == :file
+        end
+
+        # This is so that we only choose modules over mounts, not file
+        it "should choose :file when the protocol is 'file' and the fully qualified path starts with '/modules'" do
+            @request.stubs(:key).returns "/module/file"
+            @object.select_terminus(@request).should == :file
+        end
+
+        it "should fail when a protocol other than :puppet, :file, or :puppetmounts is used" do
+            @request.stubs(:key).returns "http:///module/file"
+            proc { @object.select_terminus(@request) }.should raise_error(ArgumentError)
+        end
+    end
+
+    describe "when looking for a module whose name matches the mount name" do
+        before do
+            @modules = mock 'modules'
+            @object.stubs(:terminus).with(:modules).returns(@modules)
+
+            @request.stubs(:key).returns "puppetmounts://host/mymod/file"
+        end
+
+        it "should use the modules terminus to look up the module" do
+            @modules.expects(:find_module).with("mymod", @request.options[:node])
+            @object.select_terminus @request
+        end
+
+        it "should pass the node name to the modules terminus" do
+            @modules.expects(:find_module).with("mymod", @request.options[:node])
+            @object.select_terminus @request
+        end
+
+        it "should log a deprecation warning if a module is found" do
+            @modules.expects(:find_module).with("mymod", @request.options[:node]).returns(:something)
+            Puppet.expects(:warning)
+            @object.select_terminus @request
+        end
+    end
+end
diff --git a/spec/unit/file_serving/metadata.rb b/spec/unit/file_serving/metadata.rb
new file mode 100755
index 0000000..9743370
--- /dev/null
+++ b/spec/unit/file_serving/metadata.rb
@@ -0,0 +1,171 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/metadata'
+
+describe Puppet::FileServing::Metadata do
+    it "should should be a subclass of FileBase" do
+        Puppet::FileServing::Metadata.superclass.should equal(Puppet::FileServing::FileBase)
+    end
+
+    it "should indirect file_metadata" do
+        Puppet::FileServing::Metadata.indirection.name.should == :file_metadata
+    end
+
+    it "should should include the IndirectionHooks module in its indirection" do
+        Puppet::FileServing::Metadata.indirection.metaclass.included_modules.should include(Puppet::FileServing::IndirectionHooks)
+    end
+end
+
+describe Puppet::FileServing::Metadata, " when finding the file to use for setting attributes" do
+    before do
+        @metadata = Puppet::FileServing::Metadata.new("my/path")
+
+        @full = "/base/path/my/path"
+
+        @metadata.path = @full
+
+        # Use a link because it's easier to test -- no checksumming
+        @stat = stub "stat", :uid => 10, :gid => 20, :mode => 0755, :ftype => "link"
+    end
+
+    it "should accept a base path path to which the file should be relative" do
+        File.expects(:lstat).with(@full).returns @stat
+        File.expects(:readlink).with(@full).returns "/what/ever"
+        @metadata.collect_attributes
+    end
+
+    it "should use the set base path if one is not provided" do
+        File.expects(:lstat).with(@full).returns @stat
+        File.expects(:readlink).with(@full).returns "/what/ever"
+        @metadata.collect_attributes()
+    end
+
+    it "should fail if a base path is neither set nor provided" do
+        proc { @metadata.collect_attributes() }.should raise_error(Errno::ENOENT)
+    end
+
+    it "should raise an exception if the file does not exist" do
+        File.expects(:lstat).with(@full).raises(Errno::ENOENT)
+        proc { @metadata.collect_attributes()}.should raise_error(Errno::ENOENT)
+    end
+end
+
+describe Puppet::FileServing::Metadata, " when collecting attributes" do
+    before do
+        @path = "/my/file"
+        # Use a real file mode, so we can validate the masking is done.
+        @stat = stub 'stat', :uid => 10, :gid => 20, :mode => 33261, :ftype => "file"
+        File.stubs(:lstat).returns(@stat)
+        @checksum = Digest::MD5.hexdigest("some content\n")
+        @metadata = Puppet::FileServing::Metadata.new("file", :path => "/my/file")
+        @metadata.stubs(:md5_file).returns(@checksum)
+        @metadata.collect_attributes
+    end
+
+    it "should be able to produce xmlrpc-style attribute information" do
+        @metadata.should respond_to(:attributes_with_tabs)
+    end
+
+    # LAK:FIXME This should actually change at some point
+    it "should set the owner by id" do
+        @metadata.owner.should be_instance_of(Fixnum)
+    end
+
+    # LAK:FIXME This should actually change at some point
+    it "should set the group by id" do
+        @metadata.group.should be_instance_of(Fixnum)
+    end
+
+    it "should set the owner to the file's current owner" do
+        @metadata.owner.should == 10
+    end
+
+    it "should set the group to the file's current group" do
+        @metadata.group.should == 20
+    end
+
+    it "should set the mode to the file's masked mode" do
+        @metadata.mode.should == 0755
+    end
+
+    it "should set the checksum to the file's current checksum" do
+        @metadata.checksum.should == "{md5}" + @checksum
+    end
+
+    describe "when managing files" do
+        it "should default to a checksum of type MD5" do
+            @metadata.checksum.should == "{md5}" + @checksum
+        end
+
+        it "should produce tab-separated mode, type, owner, group, and checksum for xmlrpc" do
+            @metadata.attributes_with_tabs.should == "#{0755.to_s}\tfile\t10\t20\t{md5}#{@checksum}"
+        end
+    end
+
+    describe "when managing directories" do
+        before do
+            @stat.stubs(:ftype).returns("directory")
+            @time = Time.now
+            @metadata.expects(:ctime_file).returns(@time)
+            @metadata.collect_attributes
+        end
+
+        it "should only use checksums of type 'ctime' for directories" do
+            @metadata.checksum.should == "{ctime}" + @time.to_s
+        end
+
+        it "should produce tab-separated mode, type, owner, group, and checksum for xmlrpc" do
+            @metadata.attributes_with_tabs.should == "#{0755.to_s}\tdirectory\t10\t20\t{ctime}#{@time.to_s}"
+        end
+    end
+
+    describe "when managing links" do
+        before do
+            @stat.stubs(:ftype).returns("link")
+            File.expects(:readlink).with("/my/file").returns("/path/to/link")
+            @metadata.collect_attributes
+        end
+
+        it "should read links instead of returning their checksums" do
+            @metadata.destination.should == "/path/to/link"
+        end
+
+        it "should produce tab-separated mode, type, owner, group, and destination for xmlrpc" do
+            @metadata.attributes_with_tabs.should == "#{0755.to_s}\tlink\t10\t20\t/path/to/link"
+        end
+    end
+end
+
+describe Puppet::FileServing::Metadata, " when pointing to a link" do
+    it "should store the destination of the link in :destination if links are :manage" do
+        file = Puppet::FileServing::Metadata.new("mykey", :links => :manage, :path => "/base/path/my/file")
+
+        File.expects(:lstat).with("/base/path/my/file").returns stub("stat", :uid => 1, :gid => 2, :ftype => "link", :mode => 0755)
+        File.expects(:readlink).with("/base/path/my/file").returns "/some/other/path"
+
+        file.collect_attributes
+        file.destination.should == "/some/other/path"
+    end
+
+    it "should not collect the checksum" do
+        file = Puppet::FileServing::Metadata.new("my/file", :links => :manage, :path => "/base/path/my/file")
+
+        File.expects(:lstat).with("/base/path/my/file").returns stub("stat", :uid => 1, :gid => 2, :ftype => "link", :mode => 0755)
+        File.expects(:readlink).with("/base/path/my/file").returns "/some/other/path"
+
+        file.collect_attributes
+        file.checksum.should be_nil
+    end
+end
+
+describe Puppet::FileServing::Metadata, " when converting from yaml" do
+    # LAK:FIXME This isn't in the right place, but we need some kind of
+    # control somewhere that requires that all REST connections only pull
+    # from the file-server, thus guaranteeing they go through our authorization
+    # hook.
+    it "should set the URI scheme to 'puppetmounts'" do
+        pending "We need to figure out where this should be"
+    end
+end
diff --git a/spec/unit/file_serving/mount.rb b/spec/unit/file_serving/mount.rb
new file mode 100755
index 0000000..ebe0583
--- /dev/null
+++ b/spec/unit/file_serving/mount.rb
@@ -0,0 +1,143 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/file_serving/mount'
+
+module FileServingMountTesting
+    def stub_facter(hostname)
+        Facter.stubs(:value).with("hostname").returns(hostname.sub(/\..+/, ''))
+        Facter.stubs(:value).with("domain").returns(hostname.sub(/^[^.]+\./, ''))
+    end
+end
+
+describe Puppet::FileServing::Mount do
+    it "should provide a method for clearing its cached host information" do
+        Puppet::FileServing::Mount.new("whatever").send(:localmap)
+        Puppet::FileServing::Mount.clear_cache
+        Puppet::FileServing::Mount.send(:class_variable_get, "@@localmap").should be_nil
+    end
+end
+
+describe Puppet::FileServing::Mount, " when initializing" do
+    it "should fail on non-alphanumeric name" do
+        proc { Puppet::FileServing::Mount.new("non alpha") }.should raise_error(ArgumentError)
+    end
+
+    it "should allow dashes in its name" do
+        Puppet::FileServing::Mount.new("non-alpha").name.should == "non-alpha"
+    end
+
+    it "should allow an optional path" do
+        Puppet::FileServing::Mount.new("name", "/").path.should == "/"
+    end
+end
+
+describe Puppet::FileServing::Mount, " when setting the path" do
+    before do
+        @mount = Puppet::FileServing::Mount.new("test")
+        @dir = "/this/path/does/not/exist"
+    end
+
+    it "should fail if the path is not a directory" do
+        FileTest.expects(:directory?).returns(false)
+        proc { @mount.path = @dir }.should raise_error(ArgumentError)
+    end
+
+    it "should fail if the path is not readable" do
+        FileTest.expects(:directory?).returns(true)
+        FileTest.expects(:readable?).returns(false)
+        proc { @mount.path = @dir }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::FileServing::Mount, " when finding files" do
+    include FileServingMountTesting
+
+    before do
+        FileTest.stubs(:directory?).returns(true)
+        FileTest.stubs(:readable?).returns(true)
+        @mount = Puppet::FileServing::Mount.new("test")
+        @host = "host.domain.com"
+    end
+
+    it "should fail if the mount path has not been set" do
+        proc { @mount.file_path("/blah") }.should raise_error(ArgumentError)
+    end
+
+    it "should replace incidences of %h in the path with the client's short name" do
+        @mount.path = "/dir/%h/yay"
+        @mount.path(@host).should == "/dir/host/yay"
+    end
+
+    it "should replace incidences of %H in the path with the client's fully qualified name" do
+        @mount.path = "/dir/%H/yay"
+        @mount.path(@host).should == "/dir/host.domain.com/yay"
+    end
+
+    it "should replace incidences of %d in the path with the client's domain name" do
+        @mount.path = "/dir/%d/yay"
+        @mount.path(@host).should == "/dir/domain.com/yay"
+    end
+
+    it "should perform all necessary replacements" do
+        @mount.path = "/%h/%d/%H"
+        @mount.path(@host).should == "/host/domain.com/host.domain.com"
+    end
+
+    it "should perform replacements on the base path" do
+        @mount.path = "/blah/%h"
+        @mount.file_path("/my/stuff", @host).should == "/blah/host/my/stuff"
+    end
+
+    it "should not perform replacements on the per-file path" do
+        @mount.path = "/blah"
+        @mount.file_path("/%h/stuff", @host).should == "/blah/%h/stuff"
+    end
+
+    it "should look for files relative to its base directory" do
+        @mount.path = "/blah"
+        @mount.file_path("/my/stuff", @host).should == "/blah/my/stuff"
+    end
+
+    it "should use local host information if no client data is provided" do
+        stub_facter("myhost.mydomain.com")
+        @mount.path = "/%h/%d/%H"
+        @mount.path().should == "/myhost/mydomain.com/myhost.mydomain.com"
+    end
+
+    after do
+        Puppet::FileServing::Mount.clear_cache
+    end
+end
+
+describe Puppet::FileServing::Mount, " when providing file paths" do
+    include FileServingMountTesting
+
+    before do
+        FileTest.stubs(:exists?).returns(true)
+        FileTest.stubs(:directory?).returns(true)
+        FileTest.stubs(:readable?).returns(true)
+        @mount = Puppet::FileServing::Mount.new("test", "/mount/%h")
+        stub_facter("myhost.mydomain.com")
+        @host = "host.domain.com"
+    end
+
+    it "should return nil if the file is absent" do
+        FileTest.stubs(:exists?).returns(false)
+        @mount.file("/my/path").should be_nil
+    end
+
+    it "should return the file path if the file is absent" do
+        FileTest.stubs(:exists?).with("/my/path").returns(true)
+        @mount.file("/my/path").should == "/mount/myhost/my/path"
+    end
+
+    it "should treat a nil file name as the path to the mount itself" do
+        FileTest.stubs(:exists?).returns(true)
+        @mount.file(nil).should == "/mount/myhost"
+    end
+
+    it "should use the client host name if provided in the options" do
+        @mount.file("/my/path", :node => @host).should == "/mount/host/my/path"
+    end
+end
diff --git a/spec/unit/file_serving/terminus_helper.rb b/spec/unit/file_serving/terminus_helper.rb
new file mode 100755
index 0000000..b919469
--- /dev/null
+++ b/spec/unit/file_serving/terminus_helper.rb
@@ -0,0 +1,78 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-22.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_serving/terminus_helper'
+
+describe Puppet::FileServing::TerminusHelper do
+    before do
+        @helper = Object.new
+        @helper.extend(Puppet::FileServing::TerminusHelper)
+
+        @model = mock 'model'
+        @helper.stubs(:model).returns(@model)
+    end
+
+    it "should use a fileset to find paths" do
+        fileset = mock 'fileset', :files => []
+        Puppet::FileServing::Fileset.expects(:new).with("/my/file", {}).returns(fileset)
+        @helper.path2instances("url", "/my/file")
+    end
+
+    it "should pass :recurse, :ignore, and :links settings on to the fileset if present" do
+        fileset = mock 'fileset', :files => []
+        Puppet::FileServing::Fileset.expects(:new).with("/my/file", :links => :a, :ignore => :b, :recurse => :c).returns(fileset)
+        @helper.path2instances("url", "/my/file", :links => :a, :ignore => :b, :recurse => :c)
+    end
+end
+
+
+describe Puppet::FileServing::TerminusHelper, " when creating instances" do
+    before do
+        @helper = Object.new
+        @helper.extend(Puppet::FileServing::TerminusHelper)
+
+        @model = mock 'model'
+        @helper.stubs(:model).returns(@model)
+
+        @key = "puppet://host/mount/dir"
+
+        @fileset = mock 'fileset', :files => %w{one two}
+        Puppet::FileServing::Fileset.expects(:new).returns(@fileset)
+    end
+
+    it "should create an instance of the model for each path returned by the fileset" do
+        @model.expects(:new).returns(:one)
+        @model.expects(:new).returns(:two)
+        @helper.path2instances(@key, "/my/file").length.should == 2
+    end
+
+    it "should set each instance's key to be the original key plus the file-specific path" do
+        @model.expects(:new).with { |key, options| key == @key + "/one" }.returns(:one)
+        @model.expects(:new).with { |key, options| key == @key + "/two" }.returns(:two)
+        @helper.path2instances(@key, "/my/file")
+    end
+
+    it "should set each returned instance's path to the original path" do
+        @model.expects(:new).with { |key, options| options[:path] == "/my/file" }.returns(:one)
+        @model.expects(:new).with { |key, options| options[:path] == "/my/file" }.returns(:two)
+        @helper.path2instances(@key, "/my/file")
+    end
+
+    it "should set each returned instance's relative path to the file-specific path" do
+        @model.expects(:new).with { |key, options| options[:relative_path] == "one" }.returns(:one)
+        @model.expects(:new).with { |key, options| options[:relative_path] == "two" }.returns(:two)
+        @helper.path2instances(@key, "/my/file")
+    end
+
+    it "should set the links value on each instance if one is provided" do
+        one = mock 'one', :links= => :manage
+        two = mock 'two', :links= => :manage
+        @model.expects(:new).returns(one)
+        @model.expects(:new).returns(two)
+        @helper.path2instances(@key, "/my/file", :links => :manage)
+    end
+end
diff --git a/spec/unit/indirector.rb b/spec/unit/indirector.rb
new file mode 100755
index 0000000..1efa7b2
--- /dev/null
+++ b/spec/unit/indirector.rb
@@ -0,0 +1,152 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/defaults'
+require 'puppet/indirector'
+
+describe Puppet::Indirector, " when available to a model" do
+    before do
+        @thingie = Class.new do
+            extend Puppet::Indirector
+        end
+    end
+
+    it "should provide a way for the model to register an indirection under a name" do
+        @thingie.should respond_to(:indirects)
+    end
+end
+
+describe Puppet::Indirector, "when registering an indirection" do
+    before do
+        @thingie = Class.new do
+            extend Puppet::Indirector
+            attr_reader :name
+            def initialize(name)
+                @name = name
+            end
+        end
+    end
+
+    it "should require a name when registering a model" do
+        Proc.new {@thingie.send(:indirects) }.should raise_error(ArgumentError)
+    end
+
+    it "should create an indirection instance to manage each indirecting model" do
+        @indirection = @thingie.indirects(:test)
+        @indirection.should be_instance_of(Puppet::Indirector::Indirection)
+    end
+    
+    it "should not allow a model to register under multiple names" do
+        # Keep track of the indirection instance so we can delete it on cleanup
+        @indirection = @thingie.indirects :first
+        Proc.new { @thingie.indirects :second }.should raise_error(ArgumentError)
+    end
+
+    it "should make the indirection available via an accessor" do
+        @indirection = @thingie.indirects :first
+        @thingie.indirection.should equal(@indirection)
+    end
+
+    it "should pass any provided options to the indirection during initialization" do
+        klass = mock 'terminus class'
+        Puppet::Indirector::Indirection.expects(:new).with(@thingie, :first, {:some => :options})
+        @indirection = @thingie.indirects :first, :some => :options
+    end
+
+    after do
+        @indirection.delete if @indirection
+    end
+end
+
+describe "Delegated Indirection Method", :shared => true do
+    it "should delegate to the indirection" do
+        @indirection.expects(@method)
+        @thingie.send(@method, "me")
+    end
+
+    it "should pass all of the passed arguments directly to the indirection instance" do
+        @indirection.expects(@method).with("me", :one => :two)
+        @thingie.send(@method, "me", :one => :two)
+    end
+
+    it "should return the results of the delegation as its result" do
+        request = mock 'request'
+        @indirection.expects(@method).returns "yay"
+        @thingie.send(@method, "me").should == "yay"
+    end
+end
+
+describe Puppet::Indirector, "when redirecting a model" do
+    before do
+        @thingie = Class.new do
+            extend Puppet::Indirector
+            attr_reader :name
+            def initialize(name)
+                @name = name
+            end
+        end
+        @indirection = @thingie.send(:indirects, :test)
+    end
+
+    it "should include the Envelope module in the model" do
+        @thingie.ancestors.should be_include(Puppet::Indirector::Envelope)
+    end
+
+    describe "when finding instances via the model" do
+        before { @method = :find }
+        it_should_behave_like "Delegated Indirection Method"
+    end
+
+    describe "when destroying instances via the model" do
+        before { @method = :destroy }
+        it_should_behave_like "Delegated Indirection Method"
+    end
+
+    describe "when searching for instances via the model" do
+        before { @method = :search }
+        it_should_behave_like "Delegated Indirection Method"
+    end
+
+    describe "when expiring instances via the model" do
+        before { @method = :expire }
+        it_should_behave_like "Delegated Indirection Method"
+    end
+
+    # This is an instance method, so it behaves a bit differently.
+    describe "when saving instances via the model" do
+        before do
+            @instance = @thingie.new("me")
+        end
+
+        it "should delegate to the indirection" do
+            @indirection.expects(:save)
+            @instance.save
+        end
+
+        it "should pass the instance and all arguments to the indirection's :save method" do
+            @indirection.expects(:save).with(@instance, :one => :two)
+            @instance.save :one => :two
+        end
+
+        it "should return the results of the delegation as its result" do
+            request = mock 'request'
+            @indirection.expects(:save).returns "yay"
+            @instance.save.should == "yay"
+        end
+    end
+
+    it "should give the model the ability to set the indirection terminus class" do
+        @indirection.expects(:terminus_class=).with(:myterm)
+        @thingie.terminus_class = :myterm
+    end
+
+    it "should give the model the ability to set the indirection cache class" do
+        @indirection.expects(:cache_class=).with(:mycache)
+        @thingie.cache_class = :mycache
+    end
+
+    after do
+        @indirection.delete
+    end
+end
diff --git a/spec/unit/indirector/catalog/compiler.rb b/spec/unit/indirector/catalog/compiler.rb
new file mode 100755
index 0000000..083a9ce
--- /dev/null
+++ b/spec/unit/indirector/catalog/compiler.rb
@@ -0,0 +1,162 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-23.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/catalog/compiler'
+
+describe Puppet::Node::Catalog::Compiler do
+    before do
+        Puppet.expects(:version).returns(1)
+        Facter.expects(:value).with('fqdn').returns("my.server.com")
+        Facter.expects(:value).with('ipaddress').returns("my.ip.address")
+    end
+
+    it "should gather data about itself" do
+        Puppet::Node::Catalog::Compiler.new
+    end
+
+    it "should cache the server metadata and reuse it" do
+        compiler = Puppet::Node::Catalog::Compiler.new
+        node1 = stub 'node1', :merge => nil
+        node2 = stub 'node2', :merge => nil
+        compiler.stubs(:compile)
+        Puppet::Node.stubs(:find_by_any_name).with('node1').returns(node1)
+        Puppet::Node.stubs(:find_by_any_name).with('node2').returns(node2)
+
+        compiler.find(stub('request', :key => 'node1', :options => {}))
+        compiler.find(stub('node2request', :key => 'node2', :options => {}))
+    end
+
+    it "should provide a method for determining if the catalog is networked" do
+        compiler = Puppet::Node::Catalog::Compiler.new
+        compiler.should respond_to(:networked?)
+    end
+end
+
+describe Puppet::Node::Catalog::Compiler, " when creating the interpreter" do
+    before do
+        # This gets pretty annoying on a plane where we have no IP address
+        Facter.stubs(:value).returns("whatever")
+        @compiler = Puppet::Node::Catalog::Compiler.new
+    end
+
+    it "should not create the interpreter until it is asked for the first time" do
+        interp = mock 'interp'
+        Puppet::Parser::Interpreter.expects(:new).with().returns(interp)
+        @compiler.interpreter.should equal(interp)
+    end
+
+    it "should use the same interpreter for all compiles" do
+        interp = mock 'interp'
+        Puppet::Parser::Interpreter.expects(:new).with().returns(interp)
+        @compiler.interpreter.should equal(interp)
+        @compiler.interpreter.should equal(interp)
+    end
+end
+
+describe Puppet::Node::Catalog::Compiler, " when finding nodes" do
+    before do
+        Facter.stubs(:value).returns("whatever")
+        @compiler = Puppet::Node::Catalog::Compiler.new
+        @name = "me"
+        @node = mock 'node'
+        @request = stub 'request', :key => @name, :options => {}
+        @compiler.stubs(:compile)
+    end
+
+    it "should look node information up via the Node class with the provided key" do
+        @node.stubs :merge 
+        Puppet::Node.expects(:find_by_any_name).with(@name).returns(@node)
+        @compiler.find(@request)
+    end
+end
+
+describe Puppet::Node::Catalog::Compiler, " after finding nodes" do
+    before do
+        Puppet.expects(:version).returns(1)
+        Puppet.settings.stubs(:value).with(:node_name).returns("cert")
+        Facter.expects(:value).with('fqdn').returns("my.server.com")
+        Facter.expects(:value).with('ipaddress').returns("my.ip.address")
+        @compiler = Puppet::Node::Catalog::Compiler.new
+        @name = "me"
+        @node = mock 'node'
+        @request = stub 'request', :key => @name, :options => {}
+        @compiler.stubs(:compile)
+        Puppet::Node.stubs(:find_by_any_name).with(@name).returns(@node)
+    end
+
+    it "should add the server's Puppet version to the node's parameters as 'serverversion'" do
+        @node.expects(:merge).with { |args| args["serverversion"] == "1" }
+        @compiler.find(@request)
+    end
+
+    it "should add the server's fqdn to the node's parameters as 'servername'" do
+        @node.expects(:merge).with { |args| args["servername"] == "my.server.com" }
+        @compiler.find(@request)
+    end
+
+    it "should add the server's IP address to the node's parameters as 'serverip'" do
+        @node.expects(:merge).with { |args| args["serverip"] == "my.ip.address" }
+        @compiler.find(@request)
+    end
+
+    # LAK:TODO This is going to be difficult, because this whole process is so
+    # far removed from the actual connection that the certificate information
+    # will be quite hard to come by, dum by, gum by.
+    it "should search for the name using the client certificate's DN if the :node_name setting is set to 'cert'" do
+        pending "Probably will end up in the REST work"
+    end
+end
+
+describe Puppet::Node::Catalog::Compiler, " when creating catalogs" do
+    before do
+        Facter.stubs(:value).returns("whatever")
+        env = stub 'environment', :name => "yay"
+        Puppet::Node::Environment.stubs(:new).returns(env)
+
+        @compiler = Puppet::Node::Catalog::Compiler.new
+        @name = "me"
+        @node = Puppet::Node.new @name
+        @node.stubs(:merge)
+        @request = stub 'request', :key => @name, :options => {}
+        Puppet::Node.stubs(:find_by_any_name).with(@name).returns(@node)
+    end
+
+    it "should directly use provided nodes" do
+        Puppet::Node.expects(:find_by_any_name).never
+        @compiler.interpreter.expects(:compile).with(@node)
+        @request.stubs(:options).returns(:node => @node)
+        @compiler.find(@request)
+    end
+
+    it "should fail if no node is passed and none can be found" do
+        Puppet::Node.stubs(:find_by_any_name).with(@name).returns(nil)
+        proc { @compiler.find(@request) }.should raise_error(ArgumentError)
+    end
+
+    it "should pass the found node to the interpreter for compiling" do
+        config = mock 'config'
+        @compiler.interpreter.expects(:compile).with(@node)
+        @compiler.find(@request)
+    end
+
+    it "should return the results of compiling as the catalog" do
+        config = mock 'config'
+        result = mock 'result'
+
+        @compiler.interpreter.expects(:compile).with(@node).returns(result)
+        @compiler.find(@request).should equal(result)
+    end
+
+    it "should benchmark the compile process" do
+        @compiler.stubs(:networked?).returns(true)
+        @compiler.expects(:benchmark).with do |level, message|
+            level == :notice and message =~ /^Compiled catalog/
+        end
+        @compiler.interpreter.stubs(:compile).with(@node)
+        @compiler.find(@request)
+    end
+end
diff --git a/spec/unit/indirector/catalog/yaml.rb b/spec/unit/indirector/catalog/yaml.rb
new file mode 100755
index 0000000..717fb81
--- /dev/null
+++ b/spec/unit/indirector/catalog/yaml.rb
@@ -0,0 +1,25 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/node/catalog'
+require 'puppet/indirector/catalog/yaml'
+
+describe Puppet::Node::Catalog::Yaml do
+    it "should be a subclass of the Yaml terminus" do
+        Puppet::Node::Catalog::Yaml.superclass.should equal(Puppet::Indirector::Yaml)
+    end
+
+    it "should have documentation" do
+        Puppet::Node::Catalog::Yaml.doc.should_not be_nil
+    end
+
+    it "should be registered with the catalog store indirection" do
+        indirection = Puppet::Indirector::Indirection.instance(:catalog)
+        Puppet::Node::Catalog::Yaml.indirection.should equal(indirection)
+    end
+
+    it "should have its name set to :yaml" do
+        Puppet::Node::Catalog::Yaml.name.should == :yaml
+    end
+end
diff --git a/spec/unit/indirector/checksum/file.rb b/spec/unit/indirector/checksum/file.rb
new file mode 100755
index 0000000..857d7b0
--- /dev/null
+++ b/spec/unit/indirector/checksum/file.rb
@@ -0,0 +1,139 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-22.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/checksum/file'
+
+describe Puppet::Checksum::File do
+    it "should be a subclass of the File terminus class" do
+        Puppet::Checksum::File.superclass.should equal(Puppet::Indirector::File)
+    end
+
+    it "should have documentation" do
+        Puppet::Checksum::File.doc.should be_instance_of(String)
+    end
+end
+
+describe Puppet::Checksum::File, " when initializing" do
+    it "should use the filebucket settings section" do
+        Puppet.settings.expects(:use).with(:filebucket)
+        Puppet::Checksum::File.new
+    end
+end
+
+
+describe Puppet::Checksum::File do
+    before :each do
+        Puppet.settings.stubs(:use)
+        @store = Puppet::Checksum::File.new
+
+        @value = "70924d6fa4b2d745185fa4660703a5c0"
+        @sum = stub 'sum', :name => @value
+
+        @dir = "/what/ever"
+
+        Puppet.stubs(:[]).with(:bucketdir).returns(@dir)
+
+        @path = @store.path(@value)
+
+        @request = stub 'request', :key => @value
+    end
+
+
+    describe Puppet::Checksum::File, " when determining file paths" do
+
+        # I was previously passing the object in.
+        it "should use the value passed in to path() as the checksum" do
+            @value.expects(:name).never
+            @store.path(@value)
+        end
+
+        it "should use the value of the :bucketdir setting as the root directory" do
+            @path.should =~ %r{^#{@dir}}
+        end
+
+        it "should choose a path 8 directories deep with each directory name being the respective character in the checksum" do
+            dirs = @value[0..7].split("").join(File::SEPARATOR)
+            @path.should be_include(dirs)
+        end
+
+        it "should use the full checksum as the final directory name" do
+            File.basename(File.dirname(@path)).should == @value
+        end
+
+        it "should use 'contents' as the actual file name" do
+            File.basename(@path).should == "contents"
+        end
+
+        it "should use the bucketdir, the 8 sum character directories, the full checksum, and 'contents' as the full file name" do
+            @path.should == [@dir, @value[0..7].split(""), @value, "contents"].flatten.join(File::SEPARATOR)
+        end
+    end
+
+    describe Puppet::Checksum::File, " when retrieving files" do
+
+        # The smallest test that will use the calculated path
+        it "should look for the calculated path" do
+            File.expects(:exist?).with(@path).returns(false)
+            @store.find(@request)
+        end
+
+        it "should return an instance of Puppet::Checksum created with the content if the file exists" do
+            content = "my content"
+            sum = stub 'file'
+            Puppet::Checksum.expects(:new).with(content).returns(sum)
+
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:read).with(@path).returns(content)
+
+            @store.find(@request).should equal(sum)
+        end
+
+        it "should return nil if no file is found" do
+            File.expects(:exist?).with(@path).returns(false)
+            @store.find(@request).should be_nil
+        end
+
+        it "should fail intelligently if a found file cannot be read" do
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:read).with(@path).raises(RuntimeError)
+            proc { @store.find(@request) }.should raise_error(Puppet::Error)
+        end
+    end
+
+    describe Puppet::Checksum::File, " when saving files" do
+
+        # LAK:FIXME I don't know how to include in the spec the fact that we're
+        # using the superclass's save() method and thus are acquiring all of
+        # it's behaviours.
+        it "should save the content to the calculated path" do
+            File.stubs(:directory?).with(File.dirname(@path)).returns(true)
+            File.expects(:open).with(@path, "w")
+
+            file = stub 'file', :name => @value
+            @store.save(@request)
+        end
+
+        it "should make any directories necessary for storage" do
+            FileUtils.expects(:mkdir_p).with do |arg|
+                File.umask == 0007 and arg == File.dirname(@path)
+            end
+            File.expects(:directory?).with(File.dirname(@path)).returns(true)
+            File.expects(:open).with(@path, "w")
+
+            @store.save(@request)
+        end
+    end
+
+    describe Puppet::Checksum::File, " when deleting files" do
+        it "should remove the file at the calculated path" do
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:unlink).with(@path)
+
+            @store.destroy(@request)
+        end
+    end
+end
diff --git a/spec/unit/indirector/code.rb b/spec/unit/indirector/code.rb
new file mode 100755
index 0000000..3eb7540
--- /dev/null
+++ b/spec/unit/indirector/code.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/indirector/code'
+
+describe Puppet::Indirector::Code do
+    before do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @model = mock 'model'
+        @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+        @code_class = Class.new(Puppet::Indirector::Code) do
+            def self.to_s
+                "Mystuff::Testing"
+            end
+        end
+
+        @searcher = @code_class.new
+    end
+
+    it "should not have a find() method defined" do
+        @searcher.should_not respond_to(:find)
+    end
+
+    it "should not have a save() method defined" do
+        @searcher.should_not respond_to(:save)
+    end
+
+    it "should not have a destroy() method defined" do
+        @searcher.should_not respond_to(:destroy)
+    end
+end
diff --git a/spec/unit/indirector/direct_file_server.rb b/spec/unit/indirector/direct_file_server.rb
new file mode 100755
index 0000000..a858371
--- /dev/null
+++ b/spec/unit/indirector/direct_file_server.rb
@@ -0,0 +1,98 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-24.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/direct_file_server'
+
+describe Puppet::Indirector::DirectFileServer do
+    before :each do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @model = mock 'model'
+        @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+        @direct_file_class = Class.new(Puppet::Indirector::DirectFileServer) do
+            def self.to_s
+                "Testing::Mytype"
+            end
+        end
+
+        @server = @direct_file_class.new
+
+        @uri = "file:///my/local"
+
+        @request = stub 'request', :key => @uri, :options => {}
+    end
+
+    describe Puppet::Indirector::DirectFileServer, "when finding a single file" do
+
+        it "should return nil if the file does not exist" do
+            FileTest.expects(:exists?).with("/my/local").returns false
+            @server.find(@request).should be_nil
+        end
+
+        it "should return a Content instance created with the full path to the file if the file exists" do
+            FileTest.expects(:exists?).with("/my/local").returns true
+            @model.expects(:new).returns(:mycontent)
+            @server.find(@request).should == :mycontent
+        end
+    end
+
+    describe Puppet::Indirector::DirectFileServer, "when creating the instance for a single found file" do
+
+        before do
+            @data = mock 'content'
+            @data.stubs(:collect_attributes)
+            FileTest.expects(:exists?).with("/my/local").returns true
+        end
+
+        it "should create the Content instance with the original key as the key" do
+            @model.expects(:new).with { |key, options| key == @uri }.returns(@data)
+            @server.find(@request)
+        end
+
+        it "should pass the full path to the instance" do
+            @model.expects(:new).with { |key, options| options[:path] == "/my/local" }.returns(@data)
+            @server.find(@request)
+        end
+
+        it "should pass the :links setting on to the created Content instance if the file exists and there is a value for :links" do
+            @model.expects(:new).returns(@data)
+            @data.expects(:links=).with(:manage)
+
+            @request.stubs(:options).returns(:links => :manage)
+            @server.find(@request)
+        end
+    end
+
+    describe Puppet::Indirector::DirectFileServer, "when searching for multiple files" do
+
+        it "should return nil if the file does not exist" do
+            FileTest.expects(:exists?).with("/my/local").returns false
+            @server.find(@request).should be_nil
+        end
+
+        it "should pass the original key to :path2instances" do
+            FileTest.expects(:exists?).with("/my/local").returns true
+            @server.expects(:path2instances).with { |uri, path, options| uri == @uri }
+            @server.search(@request)
+        end
+
+        it "should use :path2instances from the terminus_helper to return instances if the file exists" do
+            FileTest.expects(:exists?).with("/my/local").returns true
+            @server.expects(:path2instances)
+            @server.search(@request)
+        end
+
+        it "should pass any options on to :path2instances" do
+            FileTest.expects(:exists?).with("/my/local").returns true
+            @server.expects(:path2instances).with { |uri, path, options| options == {:testing => :one, :other => :two}}
+
+            @request.stubs(:options).returns(:testing => :one, :other => :two)
+            @server.search(@request)
+        end
+    end
+end
diff --git a/spec/unit/indirector/envelope.rb b/spec/unit/indirector/envelope.rb
new file mode 100755
index 0000000..17c6202
--- /dev/null
+++ b/spec/unit/indirector/envelope.rb
@@ -0,0 +1,47 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/indirector/envelope'
+
+describe Puppet::Indirector::Envelope do
+    before do
+        @instance = Object.new
+        @instance.extend(Puppet::Indirector::Envelope)
+    end
+
+    it "should have an expiration accessor" do
+        @instance.expiration = "testing"
+        @instance.expiration.should == "testing"
+    end
+
+    it "should have an expiration setter" do
+        @instance.should respond_to(:expiration=)
+    end
+
+    it "should have a means of testing whether it is expired" do
+        @instance.should respond_to(:expired?)
+    end
+
+    describe "when testing if it is expired" do
+        it "should return false if there is no expiration set" do
+            @instance.should_not be_expired
+        end
+
+        it "should return true if the current date is after the expiration date" do
+            @instance.expiration = Time.now - 10
+            @instance.should be_expired
+        end
+
+        it "should return false if the current date is prior to the expiration date" do
+            @instance.expiration = Time.now + 10
+            @instance.should_not be_expired
+        end
+
+        it "should return false if the current date is equal to the expiration date" do
+            now = Time.now
+            Time.stubs(:now).returns(now)
+            @instance.expiration = now
+            @instance.should_not be_expired
+        end
+    end
+end
diff --git a/spec/unit/indirector/exec.rb b/spec/unit/indirector/exec.rb
new file mode 100755
index 0000000..e474de8
--- /dev/null
+++ b/spec/unit/indirector/exec.rb
@@ -0,0 +1,51 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/exec'
+
+describe Puppet::Indirector::Exec do
+    before do
+        @indirection = stub 'indirection', :name => :testing
+        Puppet::Indirector::Indirection.expects(:instance).with(:testing).returns(@indirection)
+        @exec_class = Class.new(Puppet::Indirector::Exec) do
+            def self.to_s
+                "Testing::Mytype"
+            end
+
+            attr_accessor :command
+        end
+
+        @searcher = @exec_class.new
+        @searcher.command = ["/echo"]
+
+        @request = stub 'request', :key => "foo"
+    end
+
+    it "should throw an exception if the command is not an array" do
+        @searcher.command = "/usr/bin/echo"
+        proc { @searcher.find(@request) }.should raise_error(Puppet::DevError)
+    end
+
+    it "should throw an exception if the command is not fully qualified" do
+        @searcher.command = ["mycommand"]
+        proc { @searcher.find(@request) }.should raise_error(ArgumentError)
+    end
+
+    it "should execute the command with the object name as the only argument" do
+        @searcher.expects(:execute).with(%w{/echo foo})
+        @searcher.find(@request)
+    end
+
+    it "should return the output of the script" do
+        @searcher.expects(:execute).with(%w{/echo foo}).returns("whatever")
+        @searcher.find(@request).should == "whatever"
+    end
+
+    it "should return nil when the command produces no output" do
+        @searcher.expects(:execute).with(%w{/echo foo}).returns(nil)
+        @searcher.find(@request).should be_nil
+    end
+
+    it "should be able to execute commands with multiple arguments"
+end
diff --git a/spec/unit/indirector/facts/facter.rb b/spec/unit/indirector/facts/facter.rb
new file mode 100755
index 0000000..225eb15
--- /dev/null
+++ b/spec/unit/indirector/facts/facter.rb
@@ -0,0 +1,76 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-23.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/facts/facter'
+
+describe Puppet::Node::Facts::Facter do
+    it "should be a subclass of the Code terminus" do
+        Puppet::Node::Facts::Facter.superclass.should equal(Puppet::Indirector::Code)
+    end
+
+    it "should have documentation" do
+        Puppet::Node::Facts::Facter.doc.should_not be_nil
+    end
+
+    it "should be registered with the configuration store indirection" do
+        indirection = Puppet::Indirector::Indirection.instance(:facts)
+        Puppet::Node::Facts::Facter.indirection.should equal(indirection)
+    end
+
+    it "should have its name set to :facter" do
+        Puppet::Node::Facts::Facter.name.should == :facter
+    end
+
+    it "should load facts on initialization" do
+        Puppet::Node::Facts::Facter.expects(:loadfacts)
+        Puppet::Node::Facts::Facter.new
+    end
+end
+
+describe Puppet::Node::Facts::Facter do
+    before :each do
+        @facter = Puppet::Node::Facts::Facter.new
+        Facter.stubs(:to_hash).returns({})
+        @name = "me"
+        @request = stub 'request', :key => @name
+    end
+
+    describe Puppet::Node::Facts::Facter, " when finding facts" do
+
+        it "should return a Facts instance" do
+            @facter.find(@request).should be_instance_of(Puppet::Node::Facts)
+        end
+
+        it "should return a Facts instance with the provided key as the name" do
+            @facter.find(@request).name.should == @name
+        end
+
+        it "should return the Facter facts as the values in the Facts instance" do
+            Facter.expects(:to_hash).returns("one" => "two")
+            facts = @facter.find(@request)
+            facts.values["one"].should == "two"
+        end
+    end
+
+    describe Puppet::Node::Facts::Facter, " when saving facts" do
+
+        it "should fail" do
+            proc { @facter.save(@facts) }.should raise_error(Puppet::DevError)
+        end
+    end
+
+    describe Puppet::Node::Facts::Facter, " when destroying facts" do
+
+        it "should fail" do
+            proc { @facter.destroy(@facts) }.should raise_error(Puppet::DevError)
+        end
+    end
+
+    describe Puppet::Node::Facts::Facter, " when loading facts from the factpath" do
+        it "should load every fact in each factpath directory"
+    end
+end
diff --git a/spec/unit/indirector/facts/yaml.rb b/spec/unit/indirector/facts/yaml.rb
new file mode 100755
index 0000000..8b49fa3
--- /dev/null
+++ b/spec/unit/indirector/facts/yaml.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/node/facts'
+require 'puppet/indirector/facts/yaml'
+
+describe Puppet::Node::Facts::Yaml do
+    it "should be a subclass of the Yaml terminus" do
+        Puppet::Node::Facts::Yaml.superclass.should equal(Puppet::Indirector::Yaml)
+    end
+
+
+    it "should have documentation" do
+        Puppet::Node::Facts::Yaml.doc.should_not be_nil
+    end
+
+    it "should be registered with the facts indirection" do
+        indirection = Puppet::Indirector::Indirection.instance(:facts)
+        Puppet::Node::Facts::Yaml.indirection.should equal(indirection)
+    end
+
+    it "should have its name set to :facts" do
+        Puppet::Node::Facts::Yaml.name.should == :yaml
+    end
+end
diff --git a/spec/unit/indirector/file.rb b/spec/unit/indirector/file.rb
new file mode 100755
index 0000000..67ead4c
--- /dev/null
+++ b/spec/unit/indirector/file.rb
@@ -0,0 +1,154 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/indirector/file'
+
+
+describe Puppet::Indirector::File do
+    before :each do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @model = mock 'model'
+        @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+        @file_class = Class.new(Puppet::Indirector::File) do
+            def self.to_s
+                "Testing::Mytype"
+            end
+        end
+
+        @searcher = @file_class.new
+
+        @path = "/my/file"
+        @dir = "/my"
+
+        @request = stub 'request', :key => @path
+    end
+  
+    describe Puppet::Indirector::File, " when finding files" do
+
+        it "should provide a method to return file contents at a specified path" do
+            @searcher.should respond_to(:find)
+        end
+
+        it "should return file contents as an instance of the model" do
+            content = "my content"
+
+            file = mock 'file'
+            @model.expects(:new).with(content).returns(file)
+
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:read).with(@path).returns(content)
+            @searcher.find(@request)
+        end
+
+        it "should create the model instance with the content as the only argument to initialization" do
+            content = "my content"
+
+            file = mock 'file'
+            @model.expects(:new).with(content).returns(file)
+
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:read).with(@path).returns(content)
+            @searcher.find(@request).should equal(file)
+        end
+
+        it "should return nil if no file is found" do
+            File.expects(:exist?).with(@path).returns(false)
+            @searcher.find(@request).should be_nil
+        end
+
+        it "should fail intelligently if a found file cannot be read" do
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:read).with(@path).raises(RuntimeError)
+            proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
+        end
+
+        it "should use the path() method to calculate the path if it exists" do
+            @searcher.meta_def(:path) do |name|
+                name.upcase
+            end
+
+            File.expects(:exist?).with(@path.upcase).returns(false)
+            @searcher.find(@request)
+        end
+    end
+
+    describe Puppet::Indirector::File, " when saving files" do
+        before do
+            @content = "my content"
+            @file = stub 'file', :content => @content, :path => @path, :name => @path
+            @request.stubs(:instance).returns @file
+        end
+
+        it "should provide a method to save file contents at a specified path" do
+            filehandle = mock 'file'
+            File.expects(:directory?).with(@dir).returns(true)
+            File.expects(:open).with(@path, "w").yields(filehandle)
+            filehandle.expects(:print).with(@content)
+
+            @searcher.save(@request)
+        end
+
+        it "should fail intelligently if the file's parent directory does not exist" do
+            File.expects(:directory?).with(@dir).returns(false)
+
+            proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
+        end
+
+        it "should fail intelligently if a file cannot be written" do
+            filehandle = mock 'file'
+            File.expects(:directory?).with(@dir).returns(true)
+            File.expects(:open).with(@path, "w").yields(filehandle)
+            filehandle.expects(:print).with(@content).raises(ArgumentError)
+
+            proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
+        end
+
+        it "should use the path() method to calculate the path if it exists" do
+            @searcher.meta_def(:path) do |name|
+                name.upcase
+            end
+
+            # Reset the key to something without a parent dir, so no checks are necessary
+            @request.stubs(:key).returns "/my"
+
+            File.expects(:open).with("/MY", "w")
+            @searcher.save(@request)
+        end
+    end
+
+    describe Puppet::Indirector::File, " when removing files" do
+
+        it "should provide a method to remove files at a specified path" do
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:unlink).with(@path)
+
+            @searcher.destroy(@request)
+        end
+
+        it "should throw an exception if the file is not found" do
+            File.expects(:exist?).with(@path).returns(false)
+
+            proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
+        end
+
+        it "should fail intelligently if the file cannot be removed" do
+            File.expects(:exist?).with(@path).returns(true)
+            File.expects(:unlink).with(@path).raises(ArgumentError)
+
+            proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
+        end
+
+        it "should use the path() method to calculate the path if it exists" do
+            @searcher.meta_def(:path) do |thing|
+                thing.to_s.upcase
+            end
+
+            File.expects(:exist?).with("/MY/FILE").returns(true)
+            File.expects(:unlink).with("/MY/FILE")
+
+            @searcher.destroy(@request)
+        end
+    end
+end
diff --git a/spec/unit/indirector/file_content/file.rb b/spec/unit/indirector/file_content/file.rb
new file mode 100755
index 0000000..04656e0
--- /dev/null
+++ b/spec/unit/indirector/file_content/file.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_content/file'
+
+describe Puppet::Indirector::FileContent::File do
+    it "should be registered with the file_content indirection" do
+        Puppet::Indirector::Terminus.terminus_class(:file_content, :file).should equal(Puppet::Indirector::FileContent::File)
+    end
+
+    it "should be a subclass of the DirectFileServer terminus" do
+        Puppet::Indirector::FileContent::File.superclass.should equal(Puppet::Indirector::DirectFileServer)
+    end
+end
diff --git a/spec/unit/indirector/file_content/file_server.rb b/spec/unit/indirector/file_content/file_server.rb
new file mode 100755
index 0000000..a09c7e2
--- /dev/null
+++ b/spec/unit/indirector/file_content/file_server.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_content/file_server'
+
+describe Puppet::Indirector::FileContent::FileServer do
+    it "should be registered with the file_content indirection" do
+        Puppet::Indirector::Terminus.terminus_class(:file_content, :file_server).should equal(Puppet::Indirector::FileContent::FileServer)
+    end
+
+    it "should be a subclass of the FileServer terminus" do
+        Puppet::Indirector::FileContent::FileServer.superclass.should equal(Puppet::Indirector::FileServer)
+    end
+end
diff --git a/spec/unit/indirector/file_content/modules.rb b/spec/unit/indirector/file_content/modules.rb
new file mode 100755
index 0000000..00f02bb
--- /dev/null
+++ b/spec/unit/indirector/file_content/modules.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_content/modules'
+
+describe Puppet::Indirector::FileContent::Modules do
+    it "should be registered with the file_content indirection" do
+        Puppet::Indirector::Terminus.terminus_class(:file_content, :modules).should equal(Puppet::Indirector::FileContent::Modules)
+    end
+
+    it "should be a subclass of the ModuleFiles terminus" do
+        Puppet::Indirector::FileContent::Modules.superclass.should equal(Puppet::Indirector::ModuleFiles)
+    end
+end
diff --git a/spec/unit/indirector/file_content/rest.rb b/spec/unit/indirector/file_content/rest.rb
new file mode 100755
index 0000000..afb674e
--- /dev/null
+++ b/spec/unit/indirector/file_content/rest.rb
@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_content'
+
+describe "Puppet::Indirector::Content::Rest" do
+    it "should add the node's cert name to the arguments"
+
+    it "should set the content type to text/plain"
+end
diff --git a/spec/unit/indirector/file_metadata/file.rb b/spec/unit/indirector/file_metadata/file.rb
new file mode 100755
index 0000000..9474620
--- /dev/null
+++ b/spec/unit/indirector/file_metadata/file.rb
@@ -0,0 +1,52 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_metadata/file'
+
+describe Puppet::Indirector::FileMetadata::File do
+    it "should be registered with the file_metadata indirection" do
+        Puppet::Indirector::Terminus.terminus_class(:file_metadata, :file).should equal(Puppet::Indirector::FileMetadata::File)
+    end
+
+    it "should be a subclass of the DirectFileServer terminus" do
+        Puppet::Indirector::FileMetadata::File.superclass.should equal(Puppet::Indirector::DirectFileServer)
+    end
+
+    describe "when creating the instance for a single found file" do
+        before do
+            @metadata = Puppet::Indirector::FileMetadata::File.new
+            @uri = "file:///my/local"
+            @data = mock 'metadata'
+            @data.stubs(:collect_attributes)
+            FileTest.expects(:exists?).with("/my/local").returns true
+
+            @request = stub 'request', :key => @uri, :options => {}
+        end
+
+        it "should collect its attributes when a file is found" do
+            @data.expects(:collect_attributes)
+
+            Puppet::FileServing::Metadata.expects(:new).returns(@data)
+            @metadata.find(@request).should == @data
+        end
+    end
+
+    describe "when searching for multiple files" do
+        before do
+            @metadata = Puppet::Indirector::FileMetadata::File.new
+            @uri = "file:///my/local"
+
+            @request = stub 'request', :key => @uri, :options => {}
+        end
+
+        it "should collect the attributes of the instances returned" do
+            FileTest.expects(:exists?).with("/my/local").returns true
+            @metadata.expects(:path2instances).returns( [mock("one", :collect_attributes => nil), mock("two", :collect_attributes => nil)] )
+            @metadata.search(@request)
+        end
+    end
+end
diff --git a/spec/unit/indirector/file_metadata/file_server.rb b/spec/unit/indirector/file_metadata/file_server.rb
new file mode 100755
index 0000000..40232a1
--- /dev/null
+++ b/spec/unit/indirector/file_metadata/file_server.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_metadata/file_server'
+
+describe Puppet::Indirector::FileMetadata::FileServer do
+    it "should be registered with the file_metadata indirection" do
+        Puppet::Indirector::Terminus.terminus_class(:file_metadata, :file_server).should equal(Puppet::Indirector::FileMetadata::FileServer)
+    end
+
+    it "should be a subclass of the FileServer terminus" do
+        Puppet::Indirector::FileMetadata::FileServer.superclass.should equal(Puppet::Indirector::FileServer)
+    end
+end
diff --git a/spec/unit/indirector/file_metadata/modules.rb b/spec/unit/indirector/file_metadata/modules.rb
new file mode 100755
index 0000000..62f0183
--- /dev/null
+++ b/spec/unit/indirector/file_metadata/modules.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_metadata/modules'
+
+describe Puppet::Indirector::FileMetadata::Modules do
+    it "should be registered with the file_metadata indirection" do
+        Puppet::Indirector::Terminus.terminus_class(:file_metadata, :modules).should equal(Puppet::Indirector::FileMetadata::Modules)
+    end
+
+    it "should be a subclass of the ModuleFiles terminus" do
+        Puppet::Indirector::FileMetadata::Modules.superclass.should equal(Puppet::Indirector::ModuleFiles)
+    end
+end
+
+describe Puppet::Indirector::FileMetadata::Modules, " when finding metadata" do
+    before do
+        @finder = Puppet::Indirector::FileMetadata::Modules.new
+        @finder.stubs(:environment).returns(nil)
+        @module = Puppet::Module.new("mymod", "/path/to")
+        @finder.stubs(:find_module).returns(@module)
+    end
+
+    it "should return nil if the file is not found" do
+        FileTest.expects(:exists?).with("/path/to/files/my/file").returns false
+        @finder.find("puppetmounts://hostname/modules/mymod/my/file").should be_nil
+    end
+
+    it "should retrieve the instance's attributes if the file is found" do
+        FileTest.expects(:exists?).with("/path/to/files/my/file").returns true
+        instance = mock 'metadta'
+        Puppet::FileServing::Metadata.expects(:new).returns instance
+        instance.expects :collect_attributes
+        @finder.find("puppetmounts://hostname/modules/mymod/my/file")
+    end
+end
diff --git a/spec/unit/indirector/file_metadata/rest.rb b/spec/unit/indirector/file_metadata/rest.rb
new file mode 100755
index 0000000..e93406f
--- /dev/null
+++ b/spec/unit/indirector/file_metadata/rest.rb
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/file_metadata'
+
+describe "Puppet::Indirector::Metadata::Rest" do
+    it "should add the node's cert name to the arguments"
+end
diff --git a/spec/unit/indirector/file_server.rb b/spec/unit/indirector/file_server.rb
new file mode 100755
index 0000000..79be8cc
--- /dev/null
+++ b/spec/unit/indirector/file_server.rb
@@ -0,0 +1,168 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-19.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/file_server'
+require 'puppet/file_serving/configuration'
+
+describe Puppet::Indirector::FileServer do
+
+    before :each do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @model = mock 'model'
+        @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+        @file_server_class = Class.new(Puppet::Indirector::FileServer) do
+            def self.to_s
+                "Testing::Mytype"
+            end
+        end
+
+        @file_server = @file_server_class.new
+
+        @uri = "puppetmounts://host/my/local/file"
+        @configuration = mock 'configuration'
+        Puppet::FileServing::Configuration.stubs(:create).returns(@configuration)
+    end
+
+    describe Puppet::Indirector::FileServer, " when finding files" do
+
+        it "should use the path portion of the URI as the file name" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil)
+            @file_server.find(@uri)
+        end
+
+        it "should use the FileServing configuration to convert the file name to a fully qualified path" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil)
+            @file_server.find(@uri)
+        end
+
+        it "should pass the node name to the FileServing configuration if one is provided" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => "testing")
+            @file_server.find(@uri, :node => "testing")
+        end
+
+        it "should return nil if no fully qualified path is found" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil)
+            @file_server.find(@uri).should be_nil
+        end
+
+        it "should return an instance of the model created with the full path if a file is found" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file")
+            @model.expects(:new).returns(:myinstance)
+            @file_server.find(@uri).should == :myinstance
+        end
+    end
+
+    describe Puppet::Indirector::FileServer, " when returning instances" do
+        before :each do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file")
+            @instance = mock 'instance'
+        end
+
+        it "should create the instance with the key used to find the instance" do
+            @model.expects(:new).with { |key, *options| key == @uri }
+            @file_server.find(@uri)
+        end
+
+        it "should create the instance with the path at which the instance was found" do
+            @model.expects(:new).with { |key, options| options[:path] == "/some/file" }
+            @file_server.find(@uri)
+        end
+
+        it "should set the provided :links setting on to the instance if one is provided" do
+            @model.expects(:new).returns(@instance)
+            @instance.expects(:links=).with(:mytest)
+            @file_server.find(@uri, :links => :mytest)
+        end
+
+        it "should not set a :links value if no :links parameter is provided" do
+            @model.expects(:new).returns(@instance)
+            @file_server.find(@uri)
+        end
+    end
+
+    describe Puppet::Indirector::FileServer, " when checking authorization" do
+
+        it "should have an authorization hook" do
+            @file_server.should respond_to(:authorized?)
+        end
+
+        it "should deny the :destroy method" do
+            @file_server.authorized?(:destroy, "whatever").should be_false
+        end
+
+        it "should deny the :save method" do
+            @file_server.authorized?(:save, "whatever").should be_false
+        end
+
+        it "should use the file server configuration to determine authorization" do
+            @configuration.expects(:authorized?)
+            @file_server.authorized?(:find, "puppetmounts://host/my/file")
+        end
+
+        it "should pass the file path from the URI to the file server configuration" do
+            @configuration.expects(:authorized?).with { |uri, *args| uri == "/my/file" }
+            @file_server.authorized?(:find, "puppetmounts://host/my/file")
+        end
+
+        it "should pass the node name to the file server configuration" do
+            @configuration.expects(:authorized?).with { |key, options| options[:node] == "mynode" }
+            @file_server.authorized?(:find, "puppetmounts://host/my/file", :node => "mynode")
+        end
+
+        it "should pass the IP address to the file server configuration" do
+            @configuration.expects(:authorized?).with { |key, options| options[:ipaddress] == "myip" }
+            @file_server.authorized?(:find, "puppetmounts://host/my/file", :ipaddress => "myip")
+        end
+
+        it "should return false if the file server configuration denies authorization" do
+            @configuration.expects(:authorized?).returns(false)
+            @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_false
+        end
+
+        it "should return true if the file server configuration approves authorization" do
+            @configuration.expects(:authorized?).returns(true)
+            @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_true
+        end
+    end
+
+    describe Puppet::Indirector::FileServer, " when searching for files" do
+
+        it "should use the path portion of the URI as the file name" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil)
+            @file_server.search(@uri)
+        end
+
+        it "should use the FileServing configuration to convert the file name to a fully qualified path" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil)
+            @file_server.search(@uri)
+        end
+
+        it "should pass the node name to the FileServing configuration if one is provided" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => "testing")
+            @file_server.search(@uri, :node => "testing")
+        end
+
+        it "should return nil if no fully qualified path is found" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil)
+            @file_server.search(@uri).should be_nil
+        end
+
+        it "should use :path2instances from the terminus_helper to return instances if a module is found and the file exists" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file")
+            @file_server.expects(:path2instances).with(@uri, "/my/file", {})
+            @file_server.search(@uri)
+        end
+
+        it "should pass any options on to :path2instances" do
+            @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file")
+            @file_server.expects(:path2instances).with(@uri, "/my/file", :testing => :one, :other => :two)
+            @file_server.search(@uri, :testing => :one, :other => :two)
+        end
+    end
+end
diff --git a/spec/unit/indirector/indirection.rb b/spec/unit/indirector/indirection.rb
new file mode 100755
index 0000000..cefd055
--- /dev/null
+++ b/spec/unit/indirector/indirection.rb
@@ -0,0 +1,731 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/indirection'
+
+describe "Indirection Delegator", :shared => true do
+    it "should create a request object with the appropriate method name and all of the passed arguments" do
+        request = stub 'request', :options => {}
+
+        @indirection.expects(:request).with(@method, "mystuff", :one => :two).returns request
+
+        @terminus.stubs(@method)
+
+        @indirection.send(@method, "mystuff", :one => :two)
+    end
+
+    it "should let the :select_terminus method choose the terminus using the created request if the :select_terminus method is available" do
+        # Define the method, so our respond_to? hook matches.
+        class << @indirection
+            def select_terminus(request)
+            end
+        end
+
+        request = stub 'request', :key => "me", :options => {}
+
+        @indirection.stubs(:request).returns request
+
+        @indirection.expects(:select_terminus).with(request).returns :test_terminus
+
+        @indirection.stubs(:check_authorization)
+        @terminus.expects(@method)
+
+        @indirection.send(@method, "me")
+    end
+
+    it "should choose the terminus returned by the :terminus_class method if no :select_terminus method is available" do
+        @indirection.expects(:terminus_class).returns :test_terminus
+
+        @terminus.expects(@method)
+
+        @indirection.send(@method, "me")
+    end
+
+    it "should let the appropriate terminus perform the lookup" do
+        @terminus.expects(@method).with { |r| r.is_a?(Puppet::Indirector::Request) }
+        @indirection.send(@method, "me")
+    end
+end
+
+describe "Delegation Authorizer", :shared => true do
+    before do
+        # So the :respond_to? turns out correctly.
+        class << @terminus
+            def authorized?
+            end
+        end
+    end
+
+    it "should not check authorization if a node name is not provided" do
+        @terminus.expects(:authorized?).never
+        @terminus.stubs(@method)
+
+        # The quotes are necessary here, else it looks like a block.
+        @request.stubs(:options).returns({})
+        @indirection.send(@method, "/my/key")
+    end
+
+    it "should pass the request to the terminus's authorization method" do
+        @terminus.expects(:authorized?).with { |r| r.is_a?(Puppet::Indirector::Request) }.returns(true)
+        @terminus.stubs(@method)
+
+        @indirection.send(@method, "/my/key", :node => "mynode")
+    end
+
+    it "should fail if authorization returns false" do
+        @terminus.expects(:authorized?).returns(false)
+        @terminus.stubs(@method)
+        proc { @indirection.send(@method, "/my/key", :node => "mynode") }.should raise_error(ArgumentError)
+    end
+
+    it "should continue if authorization returns true" do
+        @terminus.expects(:authorized?).returns(true)
+        @terminus.stubs(@method)
+        @indirection.send(@method, "/my/key", :node => "mynode")
+    end
+end
+
+describe Puppet::Indirector::Indirection do
+    describe "when initializing" do
+        # (LAK) I've no idea how to test this, really.
+        it "should store a reference to itself before it consumes its options" do
+            proc { @indirection = Puppet::Indirector::Indirection.new(Object.new, :testingness, :not_valid_option) }.should raise_error
+            Puppet::Indirector::Indirection.instance(:testingness).should be_instance_of(Puppet::Indirector::Indirection)
+            Puppet::Indirector::Indirection.instance(:testingness).delete
+        end
+
+        it "should keep a reference to the indirecting model" do
+            model = mock 'model'
+            @indirection = Puppet::Indirector::Indirection.new(model, :myind)
+            @indirection.model.should equal(model)
+        end
+
+        it "should set the name" do
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :myind)
+            @indirection.name.should == :myind
+        end
+
+        it "should require indirections to have unique names" do
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            proc { Puppet::Indirector::Indirection.new(:test) }.should raise_error(ArgumentError)
+        end
+
+        it "should extend itself with any specified module" do
+            mod = Module.new
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test, :extend => mod)
+            @indirection.metaclass.included_modules.should include(mod)
+        end
+
+        after do
+            @indirection.delete if defined? @indirection
+        end
+    end
+
+    describe "when an instance" do
+        before :each do
+            @terminus_class = mock 'terminus_class'
+            @terminus = mock 'terminus'
+            @terminus_class.stubs(:new).returns(@terminus)
+            @cache = mock 'cache'
+            @cache_class = mock 'cache_class'
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class)
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class)
+
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            @indirection.terminus_class = :test_terminus
+
+            @instance = stub 'instance', :expiration => nil, :expiration= => nil, :name => "whatever"
+            @name = :mything
+
+            #@request = stub 'instance', :key => "/my/key", :instance => @instance, :options => {}
+            @request = mock 'instance'
+        end
+
+        it "should allow setting the ttl" do
+            @indirection.ttl = 300
+            @indirection.ttl.should == 300
+        end
+
+        it "should default to the :runinterval setting, converted to an integer, for its ttl" do
+            Puppet.settings.expects(:value).returns "1800"
+            @indirection.ttl.should == 1800
+        end
+
+        it "should calculate the current expiration by adding the TTL to the current time" do
+            @indirection.stubs(:ttl).returns(100)
+            now = Time.now
+            Time.stubs(:now).returns now
+            @indirection.expiration.should == (Time.now + 100)
+        end
+
+        it "should have a method for creating an indirection request instance" do
+            @indirection.should respond_to(:request)
+        end
+
+        describe "creates a request" do
+            it "should create it with its name as the request's indirection name" do
+                Puppet::Indirector::Request.expects(:new).with { |name, *other| @indirection.name == name }
+                @indirection.request(:funtest, "yayness")
+            end
+
+            it "should require a method and key" do
+                Puppet::Indirector::Request.expects(:new).with { |name, method, key, *other| method == :funtest and key == "yayness" }
+                @indirection.request(:funtest, "yayness")
+            end
+
+            it "should support optional arguments" do
+                Puppet::Indirector::Request.expects(:new).with { |name, method, key, other| other == {:one => :two} }
+                @indirection.request(:funtest, "yayness", :one => :two)
+            end
+
+            it "should default to the arguments being nil" do
+                Puppet::Indirector::Request.expects(:new).with { |name, method, key, args| args.nil? }
+                @indirection.request(:funtest, "yayness")
+            end
+
+            it "should return the request" do
+                request = mock 'request'
+                Puppet::Indirector::Request.expects(:new).returns request
+                @indirection.request(:funtest, "yayness").should equal(request)
+            end
+        end
+      
+        describe "and looking for a model instance" do
+            before { @method = :find }
+
+            it_should_behave_like "Indirection Delegator"
+            it_should_behave_like "Delegation Authorizer"
+
+            it "should return the results of the delegation" do
+                @terminus.expects(:find).returns(@instance)
+                @indirection.find("me").should equal(@instance)
+            end
+
+            it "should set the expiration date on any instances without one set" do
+                @terminus.stubs(:find).returns(@instance)
+
+                @indirection.expects(:expiration).returns :yay
+
+                @instance.expects(:expiration).returns(nil)
+                @instance.expects(:expiration=).with(:yay)
+
+                @indirection.find("/my/key")
+            end
+
+            it "should not override an already-set expiration date on returned instances" do
+                @terminus.stubs(:find).returns(@instance)
+
+                @indirection.expects(:expiration).never
+
+                @instance.expects(:expiration).returns(:yay)
+                @instance.expects(:expiration=).never
+
+                @indirection.find("/my/key")
+            end
+
+            describe "when caching is enabled" do
+                before do
+                    @indirection.cache_class = :cache_terminus
+                    @cache_class.expects(:new).returns(@cache)
+
+                    @instance.stubs(:expired?).returns false
+                end
+
+                it "should first look in the cache for an instance" do
+                    @terminus.stubs(:find).never
+                    @cache.expects(:find).returns @instance
+
+                    @indirection.find("/my/key")
+                end
+
+                it "should use a request to look in the cache for cached objects" do
+                    @cache.expects(:find).with { |r| r.method == :find and r.key == "/my/key" }.returns @instance
+
+                    @cache.stubs(:save)
+
+                    @indirection.find("/my/key")
+                end
+
+                it "should return the cached object if it is not expired" do
+                    @instance.stubs(:expired?).returns false
+
+                    @cache.stubs(:find).returns @instance
+                    @indirection.find("/my/key").should equal(@instance)
+                end
+
+                it "should send a debug log if it is using the cached object" do
+                    Puppet.expects(:debug)
+                    @cache.stubs(:find).returns @instance
+
+                    @indirection.find("/my/key")
+                end
+
+                it "should not return the cached object if it is expired" do
+                    @instance.stubs(:expired?).returns true
+
+                    @cache.stubs(:find).returns @instance
+                    @terminus.stubs(:find).returns nil
+                    @indirection.find("/my/key").should be_nil
+                end
+
+                it "should send an info log if it is using the cached object" do
+                    Puppet.expects(:info)
+                    @instance.stubs(:expired?).returns true
+
+                    @cache.stubs(:find).returns @instance
+                    @terminus.stubs(:find).returns nil
+                    @indirection.find("/my/key")
+                end
+
+                it "should cache any objects not retrieved from the cache" do
+                    @cache.expects(:find).returns nil
+
+                    @terminus.expects(:find).returns(@instance)
+                    @cache.expects(:save)
+
+                    @indirection.find("/my/key")
+                end
+
+                it "should use a request to look in the cache for cached objects" do
+                    @cache.expects(:find).with { |r| r.method == :find and r.key == "/my/key" }.returns nil
+
+                    @terminus.stubs(:find).returns(@instance)
+                    @cache.stubs(:save)
+
+                    @indirection.find("/my/key")
+                end
+
+                it "should cache the instance using a request with the instance set to the cached object" do
+                    @cache.stubs(:find).returns nil
+
+                    @terminus.stubs(:find).returns(@instance)
+
+                    @cache.expects(:save).with { |r| r.method == :save and r.instance == @instance }
+
+                    @indirection.find("/my/key")
+                end
+
+                it "should send an info log that the object is being cached" do
+                    @cache.stubs(:find).returns nil
+
+                    @terminus.stubs(:find).returns(@instance)
+                    @cache.stubs(:save)
+
+                    Puppet.expects(:info)
+
+                    @indirection.find("/my/key")
+                end
+            end
+        end
+
+        describe "and storing a model instance" do
+            before { @method = :save }
+
+            it_should_behave_like "Indirection Delegator"
+            it_should_behave_like "Delegation Authorizer"
+
+            it "should return nil" do
+                @terminus.stubs(:save)
+                @indirection.save(@instance).should be_nil
+            end
+
+            describe "when caching is enabled" do
+                before do
+                    @indirection.cache_class = :cache_terminus
+                    @cache_class.expects(:new).returns(@cache)
+
+                    @instance.stubs(:expired?).returns false
+                end
+
+                it "should use a request to save the object to the cache" do
+                    request = stub 'request', :instance => @instance, :options => {}
+
+                    @indirection.expects(:request).returns request
+
+                    @cache.expects(:save).with(request)
+                    @terminus.stubs(:save)
+                    @indirection.save(@instance)
+                end
+            end
+        end
+        
+        describe "and removing a model instance" do
+            before { @method = :destroy }
+
+            it_should_behave_like "Indirection Delegator"
+            it_should_behave_like "Delegation Authorizer"
+
+            it "should return the result of removing the instance" do
+                @terminus.stubs(:destroy).returns "yayness"
+                @indirection.destroy("/my/key").should == "yayness"
+            end
+
+            describe "when caching is enabled" do
+                before do
+                    @indirection.cache_class = :cache_terminus
+                    @cache_class.expects(:new).returns(@cache)
+
+                    @instance.stubs(:expired?).returns false
+                end
+
+                it "should use a request instance to search in and remove objects from the cache" do
+                    destroy = stub 'destroy_request', :key => "/my/key", :options => {}
+                    find = stub 'destroy_request', :key => "/my/key", :options => {}
+
+                    @indirection.expects(:request).with(:destroy, "/my/key").returns destroy
+                    @indirection.expects(:request).with(:find, "/my/key").returns find
+
+                    cached = mock 'cache'
+
+                    @cache.expects(:find).with(find).returns cached
+                    @cache.expects(:destroy).with(destroy)
+
+                    @terminus.stubs(:destroy)
+
+                    @indirection.destroy("/my/key")
+                end
+            end
+        end
+
+        describe "and searching for multiple model instances" do
+            before { @method = :search }
+
+            it_should_behave_like "Indirection Delegator"
+            it_should_behave_like "Delegation Authorizer"
+
+            it "should set the expiration date on any instances without one set" do
+                @terminus.stubs(:search).returns([@instance])
+
+                @indirection.expects(:expiration).returns :yay
+
+                @instance.expects(:expiration).returns(nil)
+                @instance.expects(:expiration=).with(:yay)
+
+                @indirection.search("/my/key")
+            end
+
+            it "should not override an already-set expiration date on returned instances" do
+                @terminus.stubs(:search).returns([@instance])
+
+                @indirection.expects(:expiration).never
+
+                @instance.expects(:expiration).returns(:yay)
+                @instance.expects(:expiration=).never
+
+                @indirection.search("/my/key")
+            end
+
+            it "should return the results of searching in the terminus" do
+                @terminus.expects(:search).returns([@instance])
+                @indirection.search("/my/key").should == [@instance]
+            end
+        end
+
+        describe "and expiring a model instance" do
+            describe "when caching is not enabled" do
+                it "should do nothing" do
+                    @cache_class.expects(:new).never
+
+                    @indirection.expire("/my/key")
+                end
+            end
+
+            describe "when caching is enabled" do
+                before do
+                    @indirection.cache_class = :cache_terminus
+                    @cache_class.expects(:new).returns(@cache)
+
+                    @instance.stubs(:expired?).returns false
+
+                    @cached = stub 'cached', :expiration= => nil, :name => "/my/key"
+                end
+
+                it "should use a request to find within the cache" do
+                    @cache.expects(:find).with { |r| r.is_a?(Puppet::Indirector::Request) and r.method == :find }
+                    @indirection.expire("/my/key")
+                end
+
+                it "should do nothing if no such instance is cached" do
+                    @cache.expects(:find).returns nil
+
+                    @indirection.expire("/my/key")
+                end
+
+                it "should log that it is expiring any found instance" do
+                    @cache.expects(:find).returns @cached
+                    @cache.stubs(:save)
+
+                    Puppet.expects(:info)
+
+                    @indirection.expire("/my/key")
+                end
+
+                it "should set the cached instance's expiration to a time in the past" do
+                    @cache.expects(:find).returns @cached
+                    @cache.stubs(:save)
+
+                    @cached.expects(:expiration=).with { |t| t < Time.now }
+
+                    @indirection.expire("/my/key")
+                end
+
+                it "should save the now expired instance back into the cache" do
+                    @cache.expects(:find).returns @cached
+
+                    @cached.expects(:expiration=).with { |t| t < Time.now }
+
+                    @cache.expects(:save)
+
+                    @indirection.expire("/my/key")
+                end
+
+                it "should use a request to save the expired resource to the cache" do
+                    @cache.expects(:find).returns @cached
+
+                    @cached.expects(:expiration=).with { |t| t < Time.now }
+
+                    @cache.expects(:save).with { |r| r.is_a?(Puppet::Indirector::Request) and r.instance == @cached and r.method == :save }.returns(@cached)
+
+                    @indirection.expire("/my/key")
+                end
+            end
+        end
+
+        after :each do
+            @indirection.delete
+            Puppet::Indirector::Indirection.clear_cache
+        end
+    end
+
+
+    describe "when managing indirection instances" do
+        it "should allow an indirection to be retrieved by name" do
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            Puppet::Indirector::Indirection.instance(:test).should equal(@indirection)
+        end
+        
+        it "should return nil when the named indirection has not been created" do
+            Puppet::Indirector::Indirection.instance(:test).should be_nil
+        end
+
+        it "should allow an indirection's model to be retrieved by name" do
+            mock_model = mock('model')
+            @indirection = Puppet::Indirector::Indirection.new(mock_model, :test)
+            Puppet::Indirector::Indirection.model(:test).should equal(mock_model)
+        end
+        
+        it "should return nil when no model matches the requested name" do
+            Puppet::Indirector::Indirection.model(:test).should be_nil
+        end
+
+        after do
+            @indirection.delete if defined? @indirection
+        end
+    end
+
+    describe "when routing to the correct the terminus class" do
+        before do
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            @terminus = mock 'terminus'
+            @terminus_class = stub 'terminus class', :new => @terminus
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :default).returns(@terminus_class)
+        end
+
+        it "should fail if no terminus class can be picked" do
+            proc { @indirection.terminus_class }.should raise_error(Puppet::DevError)
+        end
+
+        it "should choose the default terminus class if one is specified" do
+            @indirection.terminus_class = :default
+            @indirection.terminus_class.should equal(:default)
+        end
+
+        it "should use the provided Puppet setting if told to do so" do
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :my_terminus).returns(mock("terminus_class2"))
+            Puppet.settings.expects(:value).with(:my_setting).returns("my_terminus")
+            @indirection.terminus_setting = :my_setting
+            @indirection.terminus_class.should equal(:my_terminus)
+        end
+
+        it "should fail if the provided terminus class is not valid" do
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :nosuchclass).returns(nil)
+            proc { @indirection.terminus_class = :nosuchclass }.should raise_error(ArgumentError)
+        end
+
+        after do
+            @indirection.delete if defined? @indirection
+        end
+    end
+
+    describe "when specifying the terminus class to use" do
+        before do
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            @terminus = mock 'terminus'
+            @terminus_class = stub 'terminus class', :new => @terminus
+        end
+
+        it "should allow specification of a terminus type" do
+            @indirection.should respond_to(:terminus_class=)
+        end
+
+        it "should fail to redirect if no terminus type has been specified" do
+            proc { @indirection.find("blah") }.should raise_error(Puppet::DevError)
+        end
+
+        it "should fail when the terminus class name is an empty string" do
+            proc { @indirection.terminus_class = "" }.should raise_error(ArgumentError)
+        end
+
+        it "should fail when the terminus class name is nil" do
+            proc { @indirection.terminus_class = nil }.should raise_error(ArgumentError)
+        end
+
+        it "should fail when the specified terminus class cannot be found" do
+            Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
+            proc { @indirection.terminus_class = :foo }.should raise_error(ArgumentError)
+        end
+
+        it "should select the specified terminus class if a terminus class name is provided" do
+            Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(@terminus_class)
+            @indirection.terminus(:foo).should equal(@terminus)
+        end
+
+        it "should use the configured terminus class if no terminus name is specified" do
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
+            @indirection.terminus_class = :foo
+            @indirection.terminus().should equal(@terminus)
+        end
+
+        after do
+            @indirection.delete if defined? @indirection
+        end
+    end
+
+    describe "when managing terminus instances" do
+        before do
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            @terminus = mock 'terminus'
+            @terminus_class = mock 'terminus class'
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
+        end
+
+        it "should create an instance of the chosen terminus class" do
+            @terminus_class.stubs(:new).returns(@terminus)
+            @indirection.terminus(:foo).should equal(@terminus)
+        end
+
+        it "should allow the clearance of cached terminus instances" do
+            terminus1 = mock 'terminus1'
+            terminus2 = mock 'terminus2'
+            @terminus_class.stubs(:new).returns(terminus1, terminus2, ArgumentError)
+            @indirection.terminus(:foo).should equal(terminus1)
+            @indirection.class.clear_cache
+            @indirection.terminus(:foo).should equal(terminus2)
+        end
+
+        # Make sure it caches the terminus.
+        it "should return the same terminus instance each time for a given name" do
+            @terminus_class.stubs(:new).returns(@terminus)
+            @indirection.terminus(:foo).should equal(@terminus)
+            @indirection.terminus(:foo).should equal(@terminus)
+        end
+
+        it "should not create a terminus instance until one is actually needed" do
+            Puppet::Indirector.expects(:terminus).never
+            indirection = Puppet::Indirector::Indirection.new(mock('model'), :lazytest)
+        end
+
+        after do
+            @indirection.delete
+            Puppet::Indirector::Indirection.clear_cache
+        end
+    end
+
+    describe "when deciding whether to cache" do
+        before do
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            @terminus = mock 'terminus'
+            @terminus_class = mock 'terminus class'
+            @terminus_class.stubs(:new).returns(@terminus)
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
+            @indirection.terminus_class = :foo
+        end
+
+        it "should provide a method for setting the cache terminus class" do
+            @indirection.should respond_to(:cache_class=)
+        end
+
+        it "should fail to cache if no cache type has been specified" do
+            proc { @indirection.cache }.should raise_error(Puppet::DevError)
+        end
+
+        it "should fail to set the cache class when the cache class name is an empty string" do
+            proc { @indirection.cache_class = "" }.should raise_error(ArgumentError)
+        end
+
+        it "should fail to set the cache class when the cache class name is nil" do
+            proc { @indirection.cache_class = nil }.should raise_error(ArgumentError)
+        end
+
+        it "should fail to set the cache class when the specified cache class cannot be found" do
+            Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
+            proc { @indirection.cache_class = :foo }.should raise_error(ArgumentError)
+        end
+
+        after do
+            @indirection.delete
+            Puppet::Indirector::Indirection.clear_cache
+        end
+    end
+
+    describe "when using a cache" do
+        before :each do
+            Puppet.settings.stubs(:value).with("test_terminus").returns("test_terminus")
+            @terminus_class = mock 'terminus_class'
+            @terminus = mock 'terminus'
+            @terminus_class.stubs(:new).returns(@terminus)
+            @cache = mock 'cache'
+            @cache_class = mock 'cache_class'
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class)
+            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class)
+            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+            @indirection.terminus_class = :test_terminus
+        end
+
+        describe "and managing the cache terminus" do
+            it "should not create a cache terminus at initialization" do
+                # This is weird, because all of the code is in the setup.  If we got
+                # new() called on the cache class, we'd get an exception here.
+            end
+
+            it "should reuse the cache terminus" do
+                @cache_class.expects(:new).returns(@cache)
+                Puppet.settings.stubs(:value).with("test_cache").returns("cache_terminus")
+                @indirection.cache_class = :cache_terminus
+                @indirection.cache.should equal(@cache)
+                @indirection.cache.should equal(@cache)
+            end
+
+            it "should remove the cache terminus when all other terminus instances are cleared" do
+                cache2 = mock 'cache2'
+                @cache_class.stubs(:new).returns(@cache, cache2)
+                @indirection.cache_class = :cache_terminus
+                @indirection.cache.should equal(@cache)
+                @indirection.clear_cache
+                @indirection.cache.should equal(cache2)
+            end
+        end
+
+        describe "and saving" do
+        end
+        
+        describe "and finding" do
+        end
+        
+        after :each do
+            @indirection.delete
+            Puppet::Indirector::Indirection.clear_cache
+        end
+    end
+end
diff --git a/spec/unit/indirector/ldap.rb b/spec/unit/indirector/ldap.rb
new file mode 100755
index 0000000..2599bce
--- /dev/null
+++ b/spec/unit/indirector/ldap.rb
@@ -0,0 +1,149 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/ldap'
+
+describe Puppet::Indirector::Ldap, " when searching ldap" do
+    before do
+        @indirection = stub 'indirection', :name => :testing
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+        @ldap_class = Class.new(Puppet::Indirector::Ldap) do
+            def self.to_s
+                "Testing::Mytype"
+            end
+        end
+
+        @connection = mock 'ldap'
+
+        @searcher = @ldap_class.new
+
+        # Stub everything, and we can selectively replace with an expect as
+        # we need to for testing.
+        @searcher.stubs(:connection).returns(@connection)
+        @searcher.stubs(:search_filter).returns(:filter)
+        @searcher.stubs(:search_base).returns(:base)
+        @searcher.stubs(:process)
+
+        @request = stub 'request', :key => "yay"
+    end
+
+    it "should call the ldapsearch method with the name being searched for" do
+        @searcher.expects(:ldapsearch).with("yay")
+        @searcher.find @request
+    end
+
+    it "should fail if no block is passed to the ldapsearch method" do
+        proc { @searcher.ldapsearch("blah") }.should raise_error(ArgumentError)
+    end
+
+    it "should use the results of the ldapbase method as the ldap search base" do
+        @searcher.stubs(:search_base).returns("mybase")
+        @connection.expects(:search).with do |*args|
+            args[0].should == "mybase"
+            true
+        end
+        @searcher.find @request
+    end
+
+    it "should default to the value of the :search_base setting as the result of the ldapbase method" do
+        Puppet.expects(:[]).with(:ldapbase).returns("myldapbase")
+        searcher = @ldap_class.new
+        searcher.search_base.should == "myldapbase"
+    end
+
+    it "should use the results of the :search_attributes method as the list of attributes to return" do
+        @searcher.stubs(:search_attributes).returns(:myattrs)
+        @connection.expects(:search).with do |*args|
+            args[3].should == :myattrs
+            true
+        end
+        @searcher.find @request
+    end
+
+    it "should use the results of the :search_filter method as the search filter" do
+        @searcher.stubs(:search_filter).with("yay").returns("yay's filter")
+        @connection.expects(:search).with do |*args|
+            args[2].should == "yay's filter"
+            true
+        end
+        @searcher.find @request
+    end
+
+    it "should use depth 2 when searching" do
+        @connection.expects(:search).with do |*args|
+            args[1].should == 2
+            true
+        end
+        @searcher.find @request
+    end
+
+    it "should call process() on the first found entry" do
+        @connection.expects(:search).yields("myresult")
+        @searcher.expects(:process).with("yay", "myresult")
+        @searcher.find @request
+    end
+
+    it "should reconnect and retry the search if there is a failure" do
+        run = false
+        @connection.stubs(:search).with do |*args|
+            if run
+                true
+            else
+                run = true
+                raise "failed"
+            end
+        end.yields("myresult")
+        @searcher.expects(:process).with("yay", "myresult")
+
+        @searcher.find @request
+    end
+
+    it "should not reconnect on failure more than once" do
+        count = 0
+        @connection.stubs(:search).with do |*args|
+            count += 1
+            raise ArgumentError, "yay"
+        end
+        proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
+        count.should == 2
+    end
+
+    it "should return true if an entry is found" do
+        @connection.expects(:search).yields("result")
+        @searcher.ldapsearch("whatever") { |r| }.should be_true
+    end
+end
+
+describe Puppet::Indirector::Ldap, " when connecting to ldap" do
+    confine "LDAP is not available" => Puppet.features.ldap?
+    confine "No LDAP test data for networks other than Luke's" => Facter.value(:domain) == "madstop.com"
+
+    it "should only create the ldap connection when asked for it the first time"
+
+    it "should throw an exception if it cannot connect to LDAP"
+
+    it "should use SSL when the :ldapssl setting is true"
+
+    it "should connect to the server specified in the :ldapserver setting"
+
+    it "should use the port specified in the :ldapport setting"
+
+    it "should use protocol version 3"
+
+    it "should follow referrals"
+
+    it "should use the user specified in the :ldapuser setting"
+
+    it "should use the password specified in the :ldappassord setting"
+
+    it "should have an ldap method that returns an LDAP connection object"
+
+    it "should fail when LDAP support is missing"
+end
+
+describe Puppet::Indirector::Ldap, " when reconnecting to ldap" do
+    confine "Not running on culain as root" => (Puppet::Util::SUIDManager.uid == 0 and Facter.value("hostname") == "culain")
+
+    it "should reconnect to ldap when connections are lost"
+end
diff --git a/spec/unit/indirector/memory.rb b/spec/unit/indirector/memory.rb
new file mode 100755
index 0000000..3b754a1
--- /dev/null
+++ b/spec/unit/indirector/memory.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/indirector/memory'
+
+require 'shared_behaviours/memory_terminus'
+
+describe Puppet::Indirector::Memory do
+    it_should_behave_like "A Memory Terminus"
+
+    before do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @model = mock 'model'
+        @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+        @memory_class = Class.new(Puppet::Indirector::Memory) do
+            def self.to_s
+                "Mystuff::Testing"
+            end
+        end
+
+        @searcher = @memory_class.new
+        @name = "me"
+        @instance = stub 'instance', :name => @name
+
+        @request = stub 'request', :key => @name, :instance => @instance
+    end
+end
diff --git a/spec/unit/indirector/module_files.rb b/spec/unit/indirector/module_files.rb
new file mode 100755
index 0000000..0f6dbb6
--- /dev/null
+++ b/spec/unit/indirector/module_files.rb
@@ -0,0 +1,243 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-19.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/module_files'
+
+
+describe Puppet::Indirector::ModuleFiles do
+
+  before :each do
+      Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+      Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+      @model = mock 'model'
+      @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
+      Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+      @module_files_class = Class.new(Puppet::Indirector::ModuleFiles) do
+          def self.to_s
+              "Testing::Mytype"
+          end
+      end
+
+      @module_files = @module_files_class.new
+
+      @uri = "puppetmounts://host/modules/my/local/file"
+      @module = Puppet::Module.new("mymod", "/module/path")
+  end
+
+    describe Puppet::Indirector::ModuleFiles, " when finding files" do
+
+        it "should strip off the leading '/modules' mount name" do
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            @module_files.find(@uri)
+        end
+
+        it "should not strip off leading terms that start with '/modules' but are longer words" do
+            Puppet::Module.expects(:find).with('modulestart', "myenv").returns nil
+            @module_files.find("puppetmounts://host/modulestart/my/local/file")
+        end
+
+        it "should search for a module whose name is the first term in the remaining file path" do
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            @module_files.find(@uri)
+        end
+
+        it "should search for a file relative to the module's files directory" do
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file")
+            @module_files.find(@uri)
+        end
+
+        it "should return nil if the module does not exist" do
+            Puppet::Module.expects(:find).with('my', "myenv").returns nil
+            @module_files.find(@uri).should be_nil
+        end
+
+        it "should return nil if the module exists but the file does not" do
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file").returns(false)
+            @module_files.find(@uri).should be_nil
+        end
+
+        it "should return an instance of the model if a module is found and the file exists" do
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true)
+            @model.expects(:new).returns(:myinstance)
+            @module_files.find(@uri).should == :myinstance
+        end
+
+        it "should use the node's environment to look up the module if the node name is provided" do
+            node = stub "node", :environment => "testing"
+            Puppet::Node.expects(:find).with("mynode").returns(node)
+            Puppet::Module.expects(:find).with('my', "testing")
+            @module_files.find(@uri, :node => "mynode")
+        end
+
+        it "should use the default environment setting to look up the module if the node name is not provided" do
+            env = stub "environment", :name => "testing"
+            Puppet::Node::Environment.stubs(:new).returns(env)
+            Puppet::Module.expects(:find).with('my', "testing")
+            @module_files.find(@uri)
+        end
+    end
+
+    describe Puppet::Indirector::ModuleFiles, " when returning instances" do
+
+        before do
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true)
+            @instance = mock 'instance'
+        end
+
+        it "should create the instance with the key used to find the instance" do
+            @model.expects(:new).with { |key, *options| key == @uri }
+            @module_files.find(@uri)
+        end
+
+        it "should create the instance with the path at which the instance was found" do
+            @model.expects(:new).with { |key, options| options[:path] == "/module/path/files/local/file" }
+            @module_files.find(@uri)
+        end
+
+        it "should set the provided :links setting on to the instance if one is provided" do
+            @model.expects(:new).returns(@instance)
+            @instance.expects(:links=).with(:mytest)
+            @module_files.find(@uri, :links => :mytest)
+        end
+
+        it "should not set a :links value if no :links parameter is provided" do
+            @model.expects(:new).returns(@instance)
+            @module_files.find(@uri)
+        end
+    end
+
+    describe Puppet::Indirector::ModuleFiles, " when authorizing" do
+
+        before do
+            @configuration = mock 'configuration'
+            Puppet::FileServing::Configuration.stubs(:create).returns(@configuration)
+        end
+
+        it "should have an authorization hook" do
+            @module_files.should respond_to(:authorized?)
+        end
+
+        it "should deny the :destroy method" do
+            @module_files.authorized?(:destroy, "whatever").should be_false
+        end
+
+        it "should deny the :save method" do
+            @module_files.authorized?(:save, "whatever").should be_false
+        end
+
+        it "should use the file server configuration to determine authorization" do
+            @configuration.expects(:authorized?)
+            @module_files.authorized?(:find, "puppetmounts://host/my/file")
+        end
+
+        it "should use the path directly from the URI if it already includes /modules" do
+            @configuration.expects(:authorized?).with { |uri, *args| uri == "/modules/my/file" }
+            @module_files.authorized?(:find, "puppetmounts://host/modules/my/file")
+        end
+
+        it "should add /modules to the file path if it's not included in the URI" do
+            @configuration.expects(:authorized?).with { |uri, *args| uri == "/modules/my/file" }
+            @module_files.authorized?(:find, "puppetmounts://host/my/file")
+        end
+
+        it "should pass the node name to the file server configuration" do
+            @configuration.expects(:authorized?).with { |key, options| options[:node] == "mynode" }
+            @module_files.authorized?(:find, "puppetmounts://host/my/file", :node => "mynode")
+        end
+
+        it "should pass the IP address to the file server configuration" do
+            @configuration.expects(:authorized?).with { |key, options| options[:ipaddress] == "myip" }
+            @module_files.authorized?(:find, "puppetmounts://host/my/file", :ipaddress => "myip")
+        end
+
+        it "should return false if the file server configuration denies authorization" do
+            @configuration.expects(:authorized?).returns(false)
+            @module_files.authorized?(:find, "puppetmounts://host/my/file").should be_false
+        end
+
+        it "should return true if the file server configuration approves authorization" do
+            @configuration.expects(:authorized?).returns(true)
+            @module_files.authorized?(:find, "puppetmounts://host/my/file").should be_true
+        end
+    end
+
+    describe Puppet::Indirector::ModuleFiles, " when searching for files" do
+
+        it "should strip off the leading '/modules' mount name" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            @module_files.search(@uri)
+        end
+
+        it "should not strip off leading terms that start with '/modules' but are longer words" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('modulestart', "myenv").returns nil
+            @module_files.search("puppetmounts://host/modulestart/my/local/file")
+        end
+
+        it "should search for a module whose name is the first term in the remaining file path" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            @module_files.search(@uri)
+        end
+
+        it "should search for a file relative to the module's files directory" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file")
+            @module_files.search(@uri)
+        end
+
+        it "should return nil if the module does not exist" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('my', "myenv").returns nil
+            @module_files.search(@uri).should be_nil
+        end
+
+        it "should return nil if the module exists but the file does not" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file").returns(false)
+            @module_files.search(@uri).should be_nil
+        end
+
+        it "should use the node's environment to look up the module if the node name is provided" do
+            node = stub "node", :environment => "testing"
+            Puppet::Node.expects(:find).with("mynode").returns(node)
+            Puppet::Module.expects(:find).with('my', "testing")
+            @module_files.search(@uri, :node => "mynode")
+        end
+
+        it "should use the default environment setting to look up the module if the node name is not provided and the environment is not set to ''" do
+            env = stub 'env', :name => "testing"
+            Puppet::Node::Environment.stubs(:new).returns(env)
+            Puppet::Module.expects(:find).with('my', "testing")
+            @module_files.search(@uri)
+        end
+
+        it "should use :path2instances from the terminus_helper to return instances if a module is found and the file exists" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true)
+            @module_files.expects(:path2instances).with(@uri, "/module/path/files/local/file", {})
+            @module_files.search(@uri)
+        end
+
+        it "should pass any options on to :path2instances" do
+            Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv"))
+            Puppet::Module.expects(:find).with('my', "myenv").returns @module
+            FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true)
+            @module_files.expects(:path2instances).with(@uri, "/module/path/files/local/file", :testing => :one, :other => :two)
+            @module_files.search(@uri, :testing => :one, :other => :two)
+        end
+    end
+end
diff --git a/spec/unit/indirector/node/exec.rb b/spec/unit/indirector/node/exec.rb
new file mode 100755
index 0000000..09f13ab
--- /dev/null
+++ b/spec/unit/indirector/node/exec.rb
@@ -0,0 +1,69 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/node/exec'
+
+describe Puppet::Node::Exec do
+    before do
+        @indirection = mock 'indirection'
+        Puppet.settings.stubs(:value).with(:external_nodes).returns("/echo")
+        @searcher = Puppet::Node::Exec.new
+    end
+
+    describe "when constructing the command to run" do
+        it "should use the external_node script as the command" do
+            Puppet.expects(:[]).with(:external_nodes).returns("/bin/echo")
+            @searcher.command.should == %w{/bin/echo}
+        end
+
+        it "should throw an exception if no external node command is set" do
+            Puppet.expects(:[]).with(:external_nodes).returns("none")
+            proc { @searcher.find(stub('request', :key => "foo")) }.should raise_error(ArgumentError)
+        end
+    end
+
+    describe "when handling the results of the command" do
+        before do
+            @node = stub 'node', :fact_merge => nil
+            @name = "yay"
+            Puppet::Node.expects(:new).with(@name).returns(@node)
+            @result = {}
+            # Use a local variable so the reference is usable in the execute() definition.
+            result = @result
+            @searcher.meta_def(:execute) do |command|
+                return YAML.dump(result)
+            end
+
+            @request = stub 'request', :key => @name
+        end
+
+        it "should translate the YAML into a Node instance" do
+            # Use an empty hash
+            @searcher.find(@request).should equal(@node)
+        end
+
+        it "should set the resulting parameters as the node parameters" do
+            @result[:parameters] = {"a" => "b", "c" => "d"}
+            @node.expects(:parameters=).with "a" => "b", "c" => "d"
+            @searcher.find(@request)
+        end
+
+        it "should set the resulting classes as the node classes" do
+            @result[:classes] = %w{one two}
+            @node.expects(:classes=).with %w{one two}
+            @searcher.find(@request)
+        end
+
+        it "should merge the node's facts with its parameters" do
+            @node.expects(:fact_merge)
+            @searcher.find(@request)
+        end
+
+        it "should set the node's environment if one is provided" do
+            @result[:environment] = "yay"
+            @node.expects(:environment=).with "yay"
+            @searcher.find(@request)
+        end
+    end
+end
diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb
new file mode 100755
index 0000000..a406986
--- /dev/null
+++ b/spec/unit/indirector/node/ldap.rb
@@ -0,0 +1,278 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/node/ldap'
+
+describe Puppet::Node::Ldap do
+    describe "when searching for nodes" do
+        before :each do
+            @searcher = Puppet::Node::Ldap.new
+            @entries = {}
+            entries = @entries
+            
+            @connection = mock 'connection'
+            @entry = mock 'entry'
+            @connection.stubs(:search).yields(@entry)
+            @searcher.stubs(:connection).returns(@connection)
+            @searcher.stubs(:class_attributes).returns([])
+            @searcher.stubs(:parent_attribute).returns(nil)
+            @searcher.stubs(:search_base).returns(:yay)
+            @searcher.stubs(:search_filter).returns(:filter)
+
+            @node = mock 'node'
+            @node.stubs(:fact_merge)
+            @name = "mynode"
+            Puppet::Node.stubs(:new).with(@name).returns(@node)
+
+            @request = stub 'request', :key => @name
+        end
+
+        it "should return nil if no results are found in ldap" do
+            @connection.stubs(:search)
+            @searcher.find(@request).should be_nil
+        end
+
+        it "should return a node object if results are found in ldap" do
+            @entry.stubs(:to_hash).returns({})
+            @searcher.find(@request).should equal(@node)
+        end
+
+        it "should deduplicate class values" do
+            @entry.stubs(:to_hash).returns({})
+            @searcher.stubs(:class_attributes).returns(%w{one two})
+            @entry.stubs(:vals).with("one").returns(%w{a b})
+            @entry.stubs(:vals).with("two").returns(%w{b c})
+            @node.expects(:classes=).with(%w{a b c})
+            @searcher.find(@request)
+        end
+
+        it "should add any values stored in the class_attributes attributes to the node classes" do
+            @entry.stubs(:to_hash).returns({})
+            @searcher.stubs(:class_attributes).returns(%w{one two})
+            @entry.stubs(:vals).with("one").returns(%w{a b})
+            @entry.stubs(:vals).with("two").returns(%w{c d})
+            @node.expects(:classes=).with(%w{a b c d})
+            @searcher.find(@request)
+        end
+
+        it "should add all entry attributes as node parameters" do
+            @entry.stubs(:to_hash).returns("one" => ["two"], "three" => ["four"])
+            @node.expects(:parameters=).with("one" => "two", "three" => "four")
+            @searcher.find(@request)
+        end
+
+        it "should set the node's environment to the environment of the results" do
+            @entry.stubs(:to_hash).returns("environment" => ["test"])
+            @node.stubs(:parameters=)
+            @node.expects(:environment=).with("test")
+            @searcher.find(@request)
+        end
+
+        it "should retain false parameter values" do
+            @entry.stubs(:to_hash).returns("one" => [false])
+            @node.expects(:parameters=).with("one" => false)
+            @searcher.find(@request)
+        end
+
+        it "should turn single-value parameter value arrays into single non-arrays" do
+            @entry.stubs(:to_hash).returns("one" => ["a"])
+            @node.expects(:parameters=).with("one" => "a")
+            @searcher.find(@request)
+        end
+
+        it "should keep multi-valued parametes as arrays" do
+            @entry.stubs(:to_hash).returns("one" => ["a", "b"])
+            @node.expects(:parameters=).with("one" => ["a", "b"])
+            @searcher.find(@request)
+        end
+
+        describe "and a parent node is specified" do
+            before do
+                @parent = mock 'parent'
+                @parent_parent = mock 'parent_parent'
+
+                @searcher.meta_def(:search_filter) do |name|
+                    return name
+                end
+                @connection.stubs(:search).with { |*args| args[2] == @name              }.yields(@entry)
+                @connection.stubs(:search).with { |*args| args[2] == 'parent'           }.yields(@parent)
+                @connection.stubs(:search).with { |*args| args[2] == 'parent_parent'    }.yields(@parent_parent)
+
+                @searcher.stubs(:parent_attribute).returns(:parent)
+            end
+
+            it "should fail if the parent cannot be found" do
+                @connection.stubs(:search).with { |*args| args[2] == 'parent' }.returns("whatever")
+
+                @entry.stubs(:to_hash).returns({})
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+
+                proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
+            end
+
+            it "should add any parent classes to the node's classes" do
+                @entry.stubs(:to_hash).returns({})
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+                @entry.stubs(:vals).with("classes").returns(%w{a b})
+
+                @parent.stubs(:to_hash).returns({})
+                @parent.stubs(:vals).with("classes").returns(%w{c d})
+                @parent.stubs(:vals).with(:parent).returns(nil)
+
+                @searcher.stubs(:class_attributes).returns(%w{classes})
+                @node.expects(:classes=).with(%w{a b c d})
+                @searcher.find(@request)
+            end
+
+            it "should add any parent parameters to the node's parameters" do
+                @entry.stubs(:to_hash).returns("one" => "two")
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+
+                @parent.stubs(:to_hash).returns("three" => "four")
+                @parent.stubs(:vals).with(:parent).returns(nil)
+
+                @node.expects(:parameters=).with("one" => "two", "three" => "four")
+                @searcher.find(@request)
+            end
+
+            it "should prefer node parameters over parent parameters" do
+                @entry.stubs(:to_hash).returns("one" => "two")
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+
+                @parent.stubs(:to_hash).returns("one" => "three")
+                @parent.stubs(:vals).with(:parent).returns(nil)
+
+                @node.expects(:parameters=).with("one" => "two")
+                @searcher.find(@request)
+            end
+
+            it "should use the parent's environment if the node has none" do
+                @entry.stubs(:to_hash).returns({})
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+
+                @parent.stubs(:to_hash).returns("environment" => ["parent"])
+                @parent.stubs(:vals).with(:parent).returns(nil)
+
+                @node.stubs(:parameters=)
+                @node.expects(:environment=).with("parent")
+                @searcher.find(@request)
+            end
+
+            it "should prefer the node's environment to the parent's" do
+                @entry.stubs(:to_hash).returns("environment" => %w{child})
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+
+                @parent.stubs(:to_hash).returns("environment" => ["parent"])
+                @parent.stubs(:vals).with(:parent).returns(nil)
+
+                @node.stubs(:parameters=)
+                @node.expects(:environment=).with("child")
+                @searcher.find(@request)
+            end
+
+            it "should recursively look up parent information" do
+                @entry.stubs(:to_hash).returns("one" => "two")
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+
+                @parent.stubs(:to_hash).returns("three" => "four")
+                @parent.stubs(:vals).with(:parent).returns(['parent_parent'])
+
+                @parent_parent.stubs(:to_hash).returns("five" => "six")
+                @parent_parent.stubs(:vals).with(:parent).returns(nil)
+                @parent_parent.stubs(:vals).with(:parent).returns(nil)
+
+                @node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six")
+                @searcher.find(@request)
+            end
+
+            it "should not allow loops in parent declarations" do
+                @entry.stubs(:to_hash).returns("one" => "two")
+                @entry.stubs(:vals).with(:parent).returns(%w{parent})
+
+                @parent.stubs(:to_hash).returns("three" => "four")
+                @parent.stubs(:vals).with(:parent).returns([@name])
+                proc { @searcher.find(@request) }.should raise_error(ArgumentError)
+            end
+        end
+    end
+end
+
+describe Puppet::Node::Ldap, " when developing the search query" do
+    before do
+        @searcher = Puppet::Node::Ldap.new
+    end
+
+    it "should return the value of the :ldapclassattrs split on commas as the class attributes" do
+        Puppet.stubs(:[]).with(:ldapclassattrs).returns("one,two")
+        @searcher.class_attributes.should == %w{one two}
+    end
+
+    it "should return nil as the parent attribute if the :ldapparentattr is set to an empty string" do
+        Puppet.stubs(:[]).with(:ldapparentattr).returns("")
+        @searcher.parent_attribute.should be_nil
+    end
+
+    it "should return the value of the :ldapparentattr as the parent attribute" do
+        Puppet.stubs(:[]).with(:ldapparentattr).returns("pere")
+        @searcher.parent_attribute.should == "pere"
+    end
+
+    it "should use the value of the :ldapstring as the search filter" do
+        Puppet.stubs(:[]).with(:ldapstring).returns("mystring")
+        @searcher.search_filter("testing").should == "mystring"
+    end
+
+    it "should replace '%s' with the node name in the search filter if it is present" do
+        Puppet.stubs(:[]).with(:ldapstring).returns("my%sstring")
+        @searcher.search_filter("testing").should == "mytestingstring"
+    end
+
+    it "should not modify the global :ldapstring when replacing '%s' in the search filter" do
+        filter = mock 'filter'
+        filter.expects(:include?).with("%s").returns(true)
+        filter.expects(:gsub).with("%s", "testing").returns("mynewstring")
+        Puppet.stubs(:[]).with(:ldapstring).returns(filter)
+        @searcher.search_filter("testing").should == "mynewstring"
+    end
+end
+
+describe Puppet::Node::Ldap, " when deciding attributes to search for" do
+    before do
+        @searcher = Puppet::Node::Ldap.new
+    end
+
+    it "should use 'nil' if the :ldapattrs setting is 'all'" do
+        Puppet.stubs(:[]).with(:ldapattrs).returns("all")
+        @searcher.search_attributes.should be_nil
+    end
+
+    it "should split the value of :ldapattrs on commas and use the result as the attribute list" do
+        Puppet.stubs(:[]).with(:ldapattrs).returns("one,two")
+        @searcher.stubs(:class_attributes).returns([])
+        @searcher.stubs(:parent_attribute).returns(nil)
+        @searcher.search_attributes.should == %w{one two}
+    end
+
+    it "should add the class attributes to the search attributes if not returning all attributes" do
+        Puppet.stubs(:[]).with(:ldapattrs).returns("one,two")
+        @searcher.stubs(:class_attributes).returns(%w{three four})
+        @searcher.stubs(:parent_attribute).returns(nil)
+        # Sort them so i don't have to care about return order
+        @searcher.search_attributes.sort.should == %w{one two three four}.sort
+    end
+
+    it "should add the parent attribute to the search attributes if not returning all attributes" do
+        Puppet.stubs(:[]).with(:ldapattrs).returns("one,two")
+        @searcher.stubs(:class_attributes).returns([])
+        @searcher.stubs(:parent_attribute).returns("parent")
+        @searcher.search_attributes.sort.should == %w{one two parent}.sort
+    end
+
+    it "should not add nil parent attributes to the search attributes" do
+        Puppet.stubs(:[]).with(:ldapattrs).returns("one,two")
+        @searcher.stubs(:class_attributes).returns([])
+        @searcher.stubs(:parent_attribute).returns(nil)
+        @searcher.search_attributes.should == %w{one two}
+    end
+end
diff --git a/spec/unit/indirector/node/memory.rb b/spec/unit/indirector/node/memory.rb
new file mode 100755
index 0000000..71e01d4
--- /dev/null
+++ b/spec/unit/indirector/node/memory.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/node/memory'
+
+require 'shared_behaviours/memory_terminus'
+
+describe Puppet::Node::Memory do
+    before do
+        @name = "me"
+        @searcher = Puppet::Node::Memory.new
+        @instance = stub 'instance', :name => @name
+
+        @request = stub 'request', :key => @name, :instance => @instance
+    end
+
+    it_should_behave_like "A Memory Terminus"
+end
diff --git a/spec/unit/indirector/node/plain.rb b/spec/unit/indirector/node/plain.rb
new file mode 100755
index 0000000..a595998
--- /dev/null
+++ b/spec/unit/indirector/node/plain.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/node/plain'
+
+describe Puppet::Node::Plain do
+    before do
+        @searcher = Puppet::Node::Plain.new
+    end
+
+    it "should call node_merge() on the returned node" do
+        node = mock 'node'
+        Puppet::Node.expects(:new).with("mynode").returns(node)
+        node.expects(:fact_merge)
+        request = stub 'request', :key => "mynode"
+        @searcher.find(request)
+    end
+end
diff --git a/spec/unit/indirector/node/rest.rb b/spec/unit/indirector/node/rest.rb
new file mode 100755
index 0000000..3b99e33
--- /dev/null
+++ b/spec/unit/indirector/node/rest.rb
@@ -0,0 +1,13 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/node/rest'
+
+describe Puppet::Node::Rest do
+    before do
+        @searcher = Puppet::Node::Rest.new
+    end
+    
+    
+end
diff --git a/spec/unit/indirector/node/yaml.rb b/spec/unit/indirector/node/yaml.rb
new file mode 100755
index 0000000..2e6c14c
--- /dev/null
+++ b/spec/unit/indirector/node/yaml.rb
@@ -0,0 +1,25 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/node'
+require 'puppet/indirector/node/yaml'
+
+describe Puppet::Node::Yaml do
+    it "should be a subclass of the Yaml terminus" do
+        Puppet::Node::Yaml.superclass.should equal(Puppet::Indirector::Yaml)
+    end
+
+    it "should have documentation" do
+        Puppet::Node::Yaml.doc.should_not be_nil
+    end
+
+    it "should be registered with the configuration store indirection" do
+        indirection = Puppet::Indirector::Indirection.instance(:node)
+        Puppet::Node::Yaml.indirection.should equal(indirection)
+    end
+
+    it "should have its name set to :node" do
+        Puppet::Node::Yaml.name.should == :yaml
+    end
+end
diff --git a/spec/unit/indirector/plain.rb b/spec/unit/indirector/plain.rb
new file mode 100755
index 0000000..aca2816
--- /dev/null
+++ b/spec/unit/indirector/plain.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/indirector/plain'
+
+describe Puppet::Indirector::Plain do
+    before do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @model = mock 'model'
+        @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+        @plain_class = Class.new(Puppet::Indirector::Plain) do
+            def self.to_s
+                "Mystuff::Testing"
+            end
+        end
+
+        @searcher = @plain_class.new
+
+        @request = stub 'request', :key => "yay"
+    end
+
+    it "should return return an instance of the indirected model" do
+        object = mock 'object'
+        @model.expects(:new).with(@request.key).returns object
+        @searcher.find(@request).should equal(object)
+    end
+end
diff --git a/spec/unit/indirector/report/processor.rb b/spec/unit/indirector/report/processor.rb
new file mode 100755
index 0000000..bcb400b
--- /dev/null
+++ b/spec/unit/indirector/report/processor.rb
@@ -0,0 +1,77 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-23.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/report/processor'
+
+describe Puppet::Transaction::Report::Processor do
+    it "should provide a method for saving reports" do
+        Puppet::Transaction::Report::Processor.new.should respond_to(:save)
+    end
+end
+
+describe Puppet::Transaction::Report::Processor, " when saving a report" do
+    before do
+        Puppet.settings.stubs(:use)
+        @reporter = Puppet::Transaction::Report::Processor.new
+    end
+
+    it "should not process the report if reports are set to 'none'" do
+        Puppet::Reports.expects(:report).never
+        Puppet.settings.expects(:value).with(:reports).returns("none")
+
+        request = stub 'request', :instance => mock("report")
+
+        @reporter.save(request)
+    end
+
+    it "should process the report with each configured report type" do
+        Puppet.settings.stubs(:value).with(:reports).returns("one,two")
+        @reporter.send(:reports).should == %w{one two}
+    end
+end
+
+describe Puppet::Transaction::Report::Processor, " when processing a report" do
+    before do
+        Puppet.settings.stubs(:value).with(:reports).returns("one")
+        Puppet.settings.stubs(:use)
+        @reporter = Puppet::Transaction::Report::Processor.new
+
+        @report_type = mock 'one'
+        @dup_report = mock 'dupe report'
+        @dup_report.stubs(:process)
+        @report = mock 'report'
+        @report.expects(:dup).returns(@dup_report)
+
+        @request = stub 'request', :instance => @report
+
+        Puppet::Reports.expects(:report).with("one").returns(@report_type)
+
+        @dup_report.expects(:extend).with(@report_type)
+    end
+
+    # LAK:NOTE This is stupid, because the code is so short it doesn't
+    # make sense to split it out, which means I just do the same test
+    # three times so the spec looks right.
+    it "should process a duplicate of the report, not the original" do
+        @reporter.save(@request)
+    end
+
+    it "should extend the report with the report type's module" do
+        @reporter.save(@request)
+    end
+
+    it "should call the report type's :process method" do
+        @dup_report.expects(:process)
+        @reporter.save(@request)
+    end
+
+    it "should not raise exceptions" do
+        Puppet.settings.stubs(:value).with(:trace).returns(false)
+        @dup_report.expects(:process).raises(ArgumentError)
+        proc { @reporter.save(@request) }.should_not raise_error
+    end
+end
diff --git a/spec/unit/indirector/request.rb b/spec/unit/indirector/request.rb
new file mode 100755
index 0000000..cdb40b1
--- /dev/null
+++ b/spec/unit/indirector/request.rb
@@ -0,0 +1,55 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/indirector/request'
+
+describe Puppet::Indirector::Request do
+    describe "when initializing" do
+        it "should require an indirection name, a key, and a method" do
+            lambda { Puppet::Indirector::Request.new }.should raise_error(ArgumentError)
+        end
+
+        it "should use provided value as the key if it is a string" do
+            Puppet::Indirector::Request.new(:ind, :method, "mykey").key.should == "mykey"
+        end
+
+        it "should use provided value as the key if it is a symbol" do
+            Puppet::Indirector::Request.new(:ind, :method, :mykey).key.should == :mykey
+        end
+
+        it "should use the name of the provided instance as its key if an instance is provided as the key instead of a string" do
+            instance = mock 'instance', :name => "mykey"
+            request = Puppet::Indirector::Request.new(:ind, :method, instance)
+            request.key.should == "mykey"
+            request.instance.should equal(instance)
+        end
+
+        it "should support options specified as a hash" do
+            lambda { Puppet::Indirector::Request.new(:ind, :method, :key, :one => :two) }.should_not raise_error(ArgumentError)
+        end
+
+        it "should support nil options" do
+            lambda { Puppet::Indirector::Request.new(:ind, :method, :key, nil) }.should_not raise_error(ArgumentError)
+        end
+
+        it "should support unspecified options" do
+            lambda { Puppet::Indirector::Request.new(:ind, :method, :key) }.should_not raise_error(ArgumentError)
+        end
+
+        it "should fail if options are specified as anything other than nil or a hash" do
+            lambda { Puppet::Indirector::Request.new(:ind, :method, :key, [:one, :two]) }.should raise_error(ArgumentError)
+        end
+
+        it "should use an empty options hash if nil was provided" do
+            Puppet::Indirector::Request.new(:ind, :method, :key, nil).options.should == {}
+        end
+    end
+
+    it "should look use the Indirection class to return the appropriate indirection" do
+        ind = mock 'indirection'
+        Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns ind
+        request = Puppet::Indirector::Request.new(:myind, :method, :key)
+
+        request.indirection.should equal(ind)
+    end
+end
diff --git a/spec/unit/indirector/rest.rb b/spec/unit/indirector/rest.rb
new file mode 100755
index 0000000..1a10644
--- /dev/null
+++ b/spec/unit/indirector/rest.rb
@@ -0,0 +1,372 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/indirector/rest'
+
+describe Puppet::Indirector::REST do
+    before do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @model = stub('model')
+        @instance = stub('model instance')
+        @indirection = stub('indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model)
+        Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
+
+        @rest_class = Class.new(Puppet::Indirector::REST) do
+            def self.to_s
+                "This::Is::A::Test::Class"
+            end
+        end
+
+        @searcher = @rest_class.new
+    end
+    
+    describe "when locating the REST connection" do
+      before do
+        Puppet.settings.stubs(:value).returns("whatever")
+      end
+
+      it "should return the :server setting as the host" do
+        Puppet.settings.expects(:value).with(:server).returns "myserver"
+        @searcher.rest_connection_details[:host].should == "myserver"
+      end
+      
+      it "should return the :masterport (as an Integer) as the port" do
+        Puppet.settings.expects(:value).with(:masterport).returns "1234"
+        @searcher.rest_connection_details[:port].should == 1234
+      end
+    end
+    
+    describe "when doing a network fetch" do
+      before :each do
+        Net::HTTP.stubs(:start).returns('result')
+        @details = { :host => '127.0.0.1', :port => 34343 }
+        @searcher.stubs(:rest_connection_details).returns(@details)
+      end
+      
+      it "should accept a path" do
+        lambda { @search.network_fetch('foo') }.should_not raise_error(ArgumentError)
+      end
+      
+      it "should require a path" do
+        lambda { @searcher.network_fetch }.should raise_error(ArgumentError)
+      end
+            
+      it "should look up connection details" do
+        @searcher.expects(:rest_connection_details).returns(@details)
+        @searcher.network_fetch('foo')
+      end
+      
+      it "should use the GET http method" do
+        @mock_result = stub('mock result', :body => 'result')
+        @mock_connection = mock('mock http connection', :get => @mock_result)
+        @searcher.stubs(:network).yields(@mock_connection)
+        @searcher.network_fetch('foo')
+      end
+      
+      it "should use the appropriate remote server" do
+        Net::HTTP.expects(:start).with {|host, port| host == @details[:host] }
+        @searcher.network_fetch('foo')
+      end
+      
+      it "should use the appropriate remote port" do
+        Net::HTTP.expects(:start).with {|host, port| port == @details[:port] }
+        @searcher.network_fetch('foo')
+      end
+      
+      it "should use the provided path" do
+        @mock_result = stub('mock result', :body => 'result')
+        @mock_connection = stub('mock http connection')
+        @mock_connection.expects(:get).with('/foo').returns(@mock_result)
+        @searcher.stubs(:network).yields(@mock_connection)
+        @searcher.network_fetch('foo')
+      end
+                
+      it "should return the results of the GET request" do
+        @searcher.network_fetch('foo').should == 'result'        
+      end
+    end
+
+    describe "when doing a network delete" do
+      before :each do
+        Net::HTTP.stubs(:start).returns('result')
+        @details = { :host => '127.0.0.1', :port => 34343 }
+        @searcher.stubs(:rest_connection_details).returns(@details)
+      end
+      
+      it "should accept a path" do
+        lambda { @search.network_delete('foo') }.should_not raise_error(ArgumentError)
+      end
+      
+      it "should require a path" do
+        lambda { @searcher.network_delete }.should raise_error(ArgumentError)
+      end
+            
+      it "should look up connection details" do
+        @searcher.expects(:rest_connection_details).returns(@details)
+        @searcher.network_delete('foo')
+      end
+      
+      it "should use the DELETE http method" do
+        @mock_result = stub('mock result', :body => 'result')
+        @mock_connection = mock('mock http connection', :delete => @mock_result)
+        @searcher.stubs(:network).yields(@mock_connection)
+        @searcher.network_delete('foo')
+      end
+      
+      it "should use the appropriate remote server" do
+        Net::HTTP.expects(:start).with {|host, port| host == @details[:host] }
+        @searcher.network_delete('foo')
+      end
+      
+      it "should use the appropriate remote port" do
+        Net::HTTP.expects(:start).with {|host, port| port == @details[:port] }
+        @searcher.network_delete('foo')
+      end
+      
+      it "should use the provided path" do
+        @mock_result = stub('mock result', :body => 'result')
+        @mock_connection = stub('mock http connection')
+        @mock_connection.expects(:delete).with('/foo').returns(@mock_result)
+        @searcher.stubs(:network).yields(@mock_connection)
+        @searcher.network_delete('foo')
+      end
+            
+      it "should return the results of the DELETE request" do
+        @searcher.network_delete('foo').should == 'result'        
+      end    
+    end
+    
+    describe "when doing a network put" do
+      before :each do
+        Net::HTTP.stubs(:start).returns('result')
+        @details = { :host => '127.0.0.1', :port => 34343 }
+        @data = { :foo => 'bar' }
+        @searcher.stubs(:rest_connection_details).returns(@details)
+      end
+      
+      it "should accept a path and data" do
+        lambda { @search.network_put('foo', @data) }.should_not raise_error(ArgumentError)
+      end
+      
+      it "should require a path and data" do
+        lambda { @searcher.network_put('foo') }.should raise_error(ArgumentError)
+      end
+      
+      it "should look up connection details" do
+        @searcher.expects(:rest_connection_details).returns(@details)
+        @searcher.network_put('foo', @data)
+      end
+      
+      it "should use the appropriate remote server" do
+        Net::HTTP.expects(:start).with {|host, port| host == @details[:host] }
+        @searcher.network_put('foo', @data)
+      end
+      
+      it "should use the appropriate remote port" do
+        Net::HTTP.expects(:start).with {|host, port| port == @details[:port] }
+        @searcher.network_put('foo', @data)
+      end
+      
+      it "should use the PUT http method" do
+        @mock_result = stub('mock result', :body => 'result')
+        @mock_connection = mock('mock http connection', :put => @mock_result)
+        @searcher.stubs(:network).yields(@mock_connection)
+        @searcher.network_put('foo', @data)
+      end
+      
+      it "should use the provided path" do
+        @mock_result = stub('mock result', :body => 'result')
+        @mock_connection = stub('mock http connection')
+        @mock_connection.expects(:put).with {|path, data| path == '/foo' }.returns(@mock_result)
+        @searcher.stubs(:network).yields(@mock_connection)
+        @searcher.network_put('foo', @data)        
+      end
+      
+      it "should use the provided data" do
+        @mock_result = stub('mock result', :body => 'result')
+        @mock_connection = stub('mock http connection')
+        @mock_connection.expects(:put).with {|path, data| data == @data }.returns(@mock_result)
+        @searcher.stubs(:network).yields(@mock_connection)
+        @searcher.network_put('foo', @data)                
+      end
+      
+      it "should return the results of the PUT request" do
+        @searcher.network_put('foo', @data).should == 'result'        
+      end    
+    end
+
+    describe "when doing a find" do
+      before :each do
+        @result = { :foo => 'bar'}.to_yaml
+        @searcher.stubs(:network_fetch).returns(@result)  # neuter the network connection
+        @model.stubs(:from_yaml).returns(@instance)
+
+        @request = stub 'request', :key => 'foo'
+      end
+      
+      it "should look up the model instance over the network" do
+        @searcher.expects(:network_fetch).returns(@result)
+        @searcher.find(@request)
+      end
+      
+      it "should look up the model instance using the named indirection" do
+        @searcher.expects(:network_fetch).with {|path| path =~ %r{^#{@indirection.name.to_s}/} }.returns(@result)
+        @searcher.find(@request)
+      end
+      
+      it "should look up the model instance using the provided key" do
+        @searcher.expects(:network_fetch).with {|path| path =~ %r{/foo$} }.returns(@result)
+        @searcher.find(@request)
+      end
+      
+      it "should deserialize result data to a Model instance" do
+        @model.expects(:from_yaml)
+        @searcher.find(@request)
+      end
+      
+      it "should return the deserialized Model instance" do
+        @searcher.find(@request).should == @instance     
+      end
+      
+      it "should return nil when deserialized model instance is nil" do
+        @model.stubs(:from_yaml).returns(nil)
+        @searcher.find(@request).should be_nil
+      end
+      
+      it "should generate an error when result data deserializes improperly" do
+        @model.stubs(:from_yaml).raises(ArgumentError)
+        lambda { @searcher.find(@request) }.should raise_error(ArgumentError)
+      end
+      
+      it "should generate an error when result data specifies an error" do
+        @searcher.stubs(:network_fetch).returns(RuntimeError.new("bogus").to_yaml)
+        lambda { @searcher.find(@request) }.should raise_error(RuntimeError)        
+      end      
+    end
+
+    describe "when doing a search" do
+      before :each do
+        @result = [1, 2].to_yaml
+        @searcher.stubs(:network_fetch).returns(@result)
+        @model.stubs(:from_yaml).returns(@instance)
+
+        @request = stub 'request', :key => 'foo'
+      end
+      
+      it "should look up the model data over the network" do
+        @searcher.expects(:network_fetch).returns(@result)
+        @searcher.search(@request)
+      end
+      
+      it "should look up the model instance using the named indirection" do
+        @searcher.expects(:network_fetch).with {|path| path =~ %r{^#{@indirection.name.to_s}s/} }.returns(@result)
+        @searcher.search(@request)
+      end
+      
+      it "should look up the model instance using the provided key" do
+        @searcher.expects(:network_fetch).with {|path| path =~ %r{/foo$} }.returns(@result)
+        @searcher.search(@request)
+      end
+      
+      it "should deserialize result data into a list of Model instances" do
+        @model.expects(:from_yaml).at_least(2)
+        @searcher.search(@request)
+      end
+      
+      it "should generate an error when result data deserializes improperly" do
+        @model.stubs(:from_yaml).raises(ArgumentError)
+        lambda { @searcher.search(@request) }.should raise_error(ArgumentError)        
+      end
+      
+      it "should generate an error when result data specifies an error" do
+        @searcher.stubs(:network_fetch).returns(RuntimeError.new("bogus").to_yaml)
+        lambda { @searcher.search(@request) }.should raise_error(RuntimeError)        
+      end     
+    end    
+    
+    describe "when doing a destroy" do
+      before :each do
+        @result = true.to_yaml
+        @searcher.stubs(:network_delete).returns(@result)  # neuter the network connection
+        @model.stubs(:from_yaml).returns(@instance)
+
+        @request = stub 'request', :key => 'foo'
+      end
+      
+      it "should look up the model instance over the network" do
+        @searcher.expects(:network_delete).returns(@result)
+        @searcher.destroy(@request)
+      end
+      
+      it "should look up the model instance using the named indirection" do
+        @searcher.expects(:network_delete).with {|path| path =~ %r{^#{@indirection.name.to_s}/} }.returns(@result)
+        @searcher.destroy(@request)
+      end
+      
+      it "should look up the model instance using the provided key" do
+        @searcher.expects(:network_delete).with {|path| path =~ %r{/foo$} }.returns(@result)
+        @searcher.destroy(@request)
+      end
+      
+      it "should deserialize result data" do
+        YAML.expects(:load).with(@result)
+        @searcher.destroy(@request)
+      end
+      
+      it "should return deserialized result data" do
+        @searcher.destroy(@request).should == true
+      end
+      
+      it "should generate an error when result data specifies an error" do
+        @searcher.stubs(:network_delete).returns(RuntimeError.new("bogus").to_yaml)
+        lambda { @searcher.destroy(@request) }.should raise_error(RuntimeError)        
+      end      
+    end
+
+    describe "when doing a save" do
+      before :each do
+        @result = { :foo => 'bar'}.to_yaml
+        @searcher.stubs(:network_put).returns(@result)  # neuter the network connection
+        @model.stubs(:from_yaml).returns(@instance)
+
+        @request = stub 'request', :instance => @instance
+      end
+      
+      it "should save the model instance over the network" do
+        @searcher.expects(:network_put).returns(@result)
+        @searcher.save(@request)
+      end
+      
+      it "should save the model instance using the named indirection" do
+        @searcher.expects(:network_put).with do |path, data| 
+          path =~ %r{^#{@indirection.name.to_s}/} and 
+          data == @instance.to_yaml 
+        end.returns(@result)
+        @searcher.save(@request)
+      end
+      
+      it "should deserialize result data to a Model instance" do
+        @model.expects(:from_yaml)
+        @searcher.save(@request)
+      end
+      
+      it "should return the resulting deserialized Model instance" do
+        @searcher.save(@request).should == @instance     
+      end
+      
+      it "should return nil when deserialized model instance is nil" do
+        @model.stubs(:from_yaml).returns(nil)
+        @searcher.save(@request).should be_nil
+      end
+      
+      it "should generate an error when result data deserializes improperly" do
+        @model.stubs(:from_yaml).raises(ArgumentError)
+        lambda { @searcher.save(@request) }.should raise_error(ArgumentError)
+      end
+      
+      it "should generate an error when result data specifies an error" do
+        @searcher.stubs(:network_put).returns(RuntimeError.new("bogus").to_yaml)
+        lambda { @searcher.save(@request) }.should raise_error(RuntimeError)        
+      end      
+    end
+end
diff --git a/spec/unit/indirector/ssl_rsa/file.rb b/spec/unit/indirector/ssl_rsa/file.rb
new file mode 100755
index 0000000..76e5e3a
--- /dev/null
+++ b/spec/unit/indirector/ssl_rsa/file.rb
@@ -0,0 +1,116 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-22.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/sslcertificates/monkey_patch'
+require 'puppet/indirector/ssl_rsa/file'
+
+
+describe Puppet::Indirector::SslRsa::File do
+
+    it "should be a subclass of the File terminus class" do
+        Puppet::Indirector::SslRsa::File.superclass.should equal(Puppet::Indirector::File)
+    end
+    
+    it "should have documentation" do
+        Puppet::Indirector::SslRsa::File.doc.should be_instance_of(String)
+    end
+end
+
+describe Puppet::Indirector::SslRsa::File, " when choosing a path for a ca key" do
+    before do
+        @file = Puppet::Indirector::SslRsa::File.new
+        @name = :ca
+    end
+
+    it "should use the cadir" do
+        Puppet.settings.stubs(:value).with(:cadir).returns("/dir")
+        @file.path(@name).should =~ /^\/dir/
+    end
+
+    it "should use 'ca_key.pem' as the file name" do
+        @file.path(@name).should =~ /ca_key\.pem$/
+    end
+end
+
+describe Puppet::Indirector::SslRsa::File, " when choosing a path for a non-ca key" do
+    before do
+        @file = Puppet::Indirector::SslRsa::File.new
+        @name = :publickey
+    end
+
+    it "should use the publickeydir" do
+        Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir")
+        @file.path(@name).should =~ /^\/dir/
+    end
+
+    it "should use the key name with the pem file extension" do
+        @file.path(@name).should =~ /#{@name}\.pem$/
+    end
+end
+
+describe Puppet::Indirector::SslRsa::File, " when saving" do
+    before do
+        @file = Puppet::Indirector::SslRsa::File.new
+
+        Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir")
+        @key = stub "key", :name => "foo"
+    end
+
+    it "should store the rsa key to disk in pem format" do
+        @key.expects(:to_pem).returns(:data)
+        @path = "/dir/foo.pem"
+        filehandle = mock "filehandle"
+        File.expects(:open).with(@path, "w").yields(filehandle)
+        filehandle.expects(:print).with(:data)
+        @file.save(@key)
+    end
+end
+
+describe Puppet::Indirector::SslRsa::File, " when finding a key by name" do
+    before do
+        @file = Puppet::Indirector::SslRsa::File.new
+
+        Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir")
+        @name = "foo"
+    end
+
+    it "should return the key as a key object on success" do
+        @path = "/dir/foo.pem"
+        FileTest.stubs(:exists?).with(@path).returns(true)
+        File.stubs(:read).with(@path).returns(:data)
+        OpenSSL::PKey::RSA.expects(:new).with(:data).returns(:mykey)
+        @file.find(@name).should == :mykey
+    end
+
+    it "should return 'nil' on failure" do
+        @path = "/dir/foo.pem"
+        FileTest.stubs(:exists?).with(@path).returns(false)
+        @file.find(@name).should == nil
+    end
+end
+
+describe Puppet::Indirector::SslRsa::File, " when removing a key" do
+    before do
+        @file = Puppet::Indirector::SslRsa::File.new
+
+        Puppet.settings.stubs(:value).with(:publickeydir).returns("/dir")
+        @name = "foo"
+    end
+
+    it "should remove the key from disk and return true" do
+        @path = "/dir/foo.pem"
+        FileTest.stubs(:exists?).with(@path).returns(true)
+        File.stubs(:unlink).with(@path).returns(true)
+        @file.destroy(@name).should == true
+    end
+
+    it "should return an exception on failure" do
+        @path = "/dir/foo.pem"
+        FileTest.stubs(:exists?).with(@path).returns(false)
+        @file.destroy(@name).should == nil
+    end
+end
diff --git a/spec/unit/indirector/terminus.rb b/spec/unit/indirector/terminus.rb
new file mode 100755
index 0000000..3fcbf9d
--- /dev/null
+++ b/spec/unit/indirector/terminus.rb
@@ -0,0 +1,245 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/defaults'
+require 'puppet/indirector'
+require 'puppet/indirector/file'
+
+describe Puppet::Indirector::Terminus do
+    before :each do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @indirection = stub 'indirection', :name => :my_stuff, :register_terminus_type => nil
+        Puppet::Indirector::Indirection.stubs(:instance).with(:my_stuff).returns(@indirection)
+        @abstract_terminus = Class.new(Puppet::Indirector::Terminus) do
+            def self.to_s
+                "Testing::Abstract"
+            end
+        end
+        @terminus_class = Class.new(@abstract_terminus) do
+            def self.to_s
+                "MyStuff::TermType"
+            end
+        end
+        @terminus = @terminus_class.new
+    end
+
+    describe Puppet::Indirector::Terminus do
+
+        it "should provide a method for setting terminus class documentation" do
+            @terminus_class.should respond_to(:desc)
+        end
+
+        it "should support a class-level name attribute" do
+            @terminus_class.should respond_to(:name)
+        end
+
+        it "should support a class-level indirection attribute" do
+            @terminus_class.should respond_to(:indirection)
+        end
+
+        it "should support a class-level terminus-type attribute" do
+            @terminus_class.should respond_to(:terminus_type)
+        end
+
+        it "should support a class-level model attribute" do
+            @terminus_class.should respond_to(:model)
+        end
+
+        it "should accept indirection instances as its indirection" do
+            indirection = stub 'indirection', :is_a? => true, :register_terminus_type => nil
+            proc { @terminus_class.indirection = indirection }.should_not raise_error
+            @terminus_class.indirection.should equal(indirection)
+        end
+
+        it "should look up indirection instances when only a name has been provided" do
+            indirection = mock 'indirection'
+            Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns(indirection)
+            @terminus_class.indirection = :myind
+            @terminus_class.indirection.should equal(indirection)
+        end
+
+        it "should fail when provided a name that does not resolve to an indirection" do
+            Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns(nil)
+            proc { @terminus_class.indirection = :myind }.should raise_error(ArgumentError)
+
+            # It shouldn't overwrite our existing one (or, more normally, it shouldn't set
+            # anything).
+            @terminus_class.indirection.should equal(@indirection)
+        end
+    end
+
+    describe Puppet::Indirector::Terminus, " when creating terminus classes" do
+        it "should associate the subclass with an indirection based on the subclass constant" do
+            @terminus.indirection.should equal(@indirection)
+        end
+
+        it "should set the subclass's type to the abstract terminus name" do
+            @terminus.terminus_type.should == :abstract
+        end
+
+        it "should set the subclass's name to the indirection name" do
+            @terminus.name.should == :term_type
+        end
+
+        it "should set the subclass's model to the indirection model" do
+            @indirection.expects(:model).returns :yay
+            @terminus.model.should == :yay
+        end
+    end
+
+    describe Puppet::Indirector::Terminus, " when a terminus instance" do
+
+        it "should return the class's name as its name" do
+            @terminus.name.should == :term_type
+        end
+
+        it "should return the class's indirection as its indirection" do
+            @terminus.indirection.should equal(@indirection)
+        end
+
+        it "should set the instances's type to the abstract terminus type's name" do
+            @terminus.terminus_type.should == :abstract
+        end
+
+        it "should set the instances's model to the indirection's model" do
+            @indirection.expects(:model).returns :yay
+            @terminus.model.should == :yay
+        end
+    end
+end
+
+# LAK: This could reasonably be in the Indirection instances, too.  It doesn't make
+# a whole heckuva lot of difference, except that with the instance loading in
+# the Terminus base class, we have to have a check to see if we're already
+# instance-loading a given terminus class type.
+describe Puppet::Indirector::Terminus, " when managing terminus classes" do
+    it "should provide a method for registering terminus classes" do
+        Puppet::Indirector::Terminus.should respond_to(:register_terminus_class)
+    end
+
+    it "should provide a method for returning terminus classes by name and type" do
+        terminus = stub 'terminus_type', :name => :abstract, :indirection_name => :whatever
+        Puppet::Indirector::Terminus.register_terminus_class(terminus)
+        Puppet::Indirector::Terminus.terminus_class(:whatever, :abstract).should equal(terminus)
+    end
+
+    it "should set up autoloading for any terminus class types requested" do
+        Puppet::Indirector::Terminus.expects(:instance_load).with(:test2, "puppet/indirector/test2")
+        Puppet::Indirector::Terminus.terminus_class(:test2, :whatever)
+    end
+
+    it "should load terminus classes that are not found" do
+        # Set up instance loading; it would normally happen automatically
+        Puppet::Indirector::Terminus.instance_load :test1, "puppet/indirector/test1"
+
+        Puppet::Indirector::Terminus.instance_loader(:test1).expects(:load).with(:yay)
+        Puppet::Indirector::Terminus.terminus_class(:test1, :yay)
+    end
+
+    it "should fail when no indirection can be found" do
+        Puppet::Indirector::Indirection.expects(:instance).with(:my_indirection).returns(nil)
+
+        @abstract_terminus = Class.new(Puppet::Indirector::Terminus) do
+            def self.to_s
+                "Abstract"
+            end
+        end
+        proc {
+            @terminus = Class.new(@abstract_terminus) do
+                def self.to_s
+                    "MyIndirection::TestType"
+                end
+            end
+        }.should raise_error(ArgumentError)
+    end
+
+    it "should register the terminus class with the terminus base class" do
+        Puppet::Indirector::Terminus.expects(:register_terminus_class).with do |type|
+            type.indirection_name == :my_indirection and type.name == :test_terminus
+        end
+        @indirection = stub 'indirection', :name => :my_indirection, :register_terminus_type => nil
+        Puppet::Indirector::Indirection.expects(:instance).with(:my_indirection).returns(@indirection)
+
+        @abstract_terminus = Class.new(Puppet::Indirector::Terminus) do
+            def self.to_s
+                "Abstract"
+            end
+        end
+
+        @terminus = Class.new(@abstract_terminus) do
+            def self.to_s
+                "MyIndirection::TestTerminus"
+            end
+        end
+    end
+end
+
+describe Puppet::Indirector::Terminus, " when parsing class constants for indirection and terminus names" do
+    before do
+        @subclass = mock 'subclass'
+        @subclass.stubs(:to_s).returns("TestInd::OneTwo")
+        @subclass.stubs(:mark_as_abstract_terminus)
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+    end
+
+    it "should fail when anonymous classes are used" do
+        proc { Puppet::Indirector::Terminus.inherited(Class.new) }.should raise_error(Puppet::DevError)
+    end
+
+    it "should use the last term in the constant for the terminus class name" do
+        @subclass.expects(:name=).with(:one_two)
+        @subclass.stubs(:indirection=)
+        Puppet::Indirector::Terminus.inherited(@subclass)
+    end
+
+    it "should convert the terminus name to a downcased symbol" do
+        @subclass.expects(:name=).with(:one_two)
+        @subclass.stubs(:indirection=)
+        Puppet::Indirector::Terminus.inherited(@subclass)
+    end
+
+    it "should use the second to last term in the constant for the indirection name" do
+        @subclass.expects(:indirection=).with(:test_ind)
+        @subclass.stubs(:name=)
+        @subclass.stubs(:terminus_type=)
+        Puppet::Indirector::File.inherited(@subclass)
+    end
+
+    it "should convert the indirection name to a downcased symbol" do
+        @subclass.expects(:indirection=).with(:test_ind)
+        @subclass.stubs(:name=)
+        @subclass.stubs(:terminus_type=)
+        Puppet::Indirector::File.inherited(@subclass)
+    end
+
+    it "should convert camel case to lower case with underscores as word separators" do
+        @subclass.expects(:name=).with(:one_two)
+        @subclass.stubs(:indirection=)
+
+        Puppet::Indirector::Terminus.inherited(@subclass)
+    end
+end
+
+describe Puppet::Indirector::Terminus, " when creating terminus class types" do
+    before do
+        Puppet::Indirector::Terminus.stubs(:register_terminus_class)
+        @subclass = Class.new(Puppet::Indirector::Terminus) do
+            def self.to_s
+                "Puppet::Indirector::Terminus::MyTermType"
+            end
+        end
+    end
+
+    it "should set the name of the abstract subclass to be its class constant" do
+        @subclass.name.should equal(:my_term_type)
+    end
+
+    it "should mark abstract terminus types as such" do
+        @subclass.should be_abstract_terminus
+    end
+
+    it "should not allow instances of abstract subclasses to be created" do
+        proc { @subclass.new }.should raise_error(Puppet::DevError)
+    end
+end
+
diff --git a/spec/unit/indirector/yaml.rb b/spec/unit/indirector/yaml.rb
new file mode 100755
index 0000000..53d12f4
--- /dev/null
+++ b/spec/unit/indirector/yaml.rb
@@ -0,0 +1,96 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/indirector/yaml'
+
+describe Puppet::Indirector::Yaml, " when choosing file location" do
+    before :each do
+        @indirection = stub 'indirection', :name => :my_yaml, :register_terminus_type => nil
+        Puppet::Indirector::Indirection.stubs(:instance).with(:my_yaml).returns(@indirection)
+        @store_class = Class.new(Puppet::Indirector::Yaml) do
+            def self.to_s
+                "MyYaml::MyType"
+            end
+        end
+        @store = @store_class.new
+
+        @subject = Object.new
+        @subject.metaclass.send(:attr_accessor, :name)
+        @subject.name = :me
+
+        @dir = "/what/ever"
+        Puppet.settings.stubs(:value).with(:yamldir).returns(@dir)
+
+        @request = stub 'request', :key => :me, :instance => @subject
+    end
+
+    describe Puppet::Indirector::Yaml, " when choosing file location" do
+        it "should store all files in a single file root set in the Puppet defaults" do
+            @store.path(:me).should =~ %r{^#{@dir}}
+        end
+
+        it "should use the terminus name for choosing the subdirectory" do
+            @store.path(:me).should =~ %r{^#{@dir}/my_yaml}
+        end
+
+        it "should use the object's name to determine the file name" do
+            @store.path(:me).should =~ %r{me.yaml$}
+        end
+    end
+
+    describe Puppet::Indirector::Yaml, " when storing objects as YAML" do
+        it "should only store objects that respond to :name" do
+            @request.stubs(:instance).returns Object.new
+            proc { @store.save(@request) }.should raise_error(ArgumentError)
+        end
+
+        it "should convert Ruby objects to YAML and write them to disk" do
+            yaml = @subject.to_yaml
+            file = mock 'file'
+            path = @store.send(:path, @subject.name)
+            FileTest.expects(:exist?).with(File.dirname(path)).returns(true)
+            File.expects(:open).with(path, "w", 0660).yields(file)
+            file.expects(:print).with(yaml)
+
+            @store.save(@request)
+        end
+
+        it "should create the indirection subdirectory if it does not exist" do
+            yaml = @subject.to_yaml
+            file = mock 'file'
+            path = @store.send(:path, @subject.name)
+            dir = File.dirname(path)
+            FileTest.expects(:exist?).with(dir).returns(false)
+            Dir.expects(:mkdir).with(dir)
+            File.expects(:open).with(path, "w", 0660).yields(file)
+            file.expects(:print).with(yaml)
+
+            @store.save(@request)
+        end
+    end
+
+    describe Puppet::Indirector::Yaml, " when retrieving YAML" do
+        it "should read YAML in from disk and convert it to Ruby objects" do
+            path = @store.send(:path, @subject.name)
+
+            yaml = @subject.to_yaml
+            FileTest.expects(:exist?).with(path).returns(true)
+            File.expects(:read).with(path).returns(yaml)
+
+            @store.find(@request).instance_variable_get("@name").should == :me
+        end
+
+        it "should fail coherently when the stored YAML is invalid" do
+            path = @store.send(:path, @subject.name)
+
+            # Something that will fail in yaml
+            yaml = "--- !ruby/object:Hash"
+
+            FileTest.expects(:exist?).with(path).returns(true)
+            File.expects(:read).with(path).returns(yaml)
+
+            proc { @store.find(@request) }.should raise_error(Puppet::Error)
+        end
+    end
+end
diff --git a/spec/unit/module.rb b/spec/unit/module.rb
new file mode 100755
index 0000000..06b2d01
--- /dev/null
+++ b/spec/unit/module.rb
@@ -0,0 +1,198 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe Puppet::Module, " when building its search path" do
+    include PuppetTest
+
+    it "should fully qualify unqualified paths in the search path" do
+        Puppet[:modulepath] = "something:/my/something"
+        File.stubs(:directory?).returns(true)
+        Puppet::Module.modulepath.should == [File.join(Dir.getwd, 'something'), "/my/something"]
+    end
+
+    it "should ignore paths that do not exist" do
+        Puppet[:modulepath] = "/yes:/no"
+        File.expects(:directory?).with("/yes").returns(true)
+        File.expects(:directory?).with("/no").returns(false)
+        Puppet::Module.modulepath.should == %w{/yes}
+    end
+
+    it "should prepend PUPPETLIB in search path when set" do
+        Puppet[:modulepath] = "/my/mod:/other/mod"
+        ENV["PUPPETLIB"] = "/env/mod:/myenv/mod"
+        File.stubs(:directory?).returns(true)
+        Puppet::Module.modulepath.should == %w{/env/mod /myenv/mod /my/mod /other/mod}
+    end
+
+    it "should use the environment-specific search path when a node environment is provided" do
+        Puppet.settings.expects(:value).with(:modulepath, "myenv").returns("/mone:/mtwo")
+        File.stubs(:directory?).returns(true)
+        Puppet::Module.modulepath("myenv").should == %w{/mone /mtwo}
+    end
+
+    after do
+        ENV["PUPPETLIB"] = nil
+    end
+end
+
+describe Puppet::Module, " when searching for modules" do
+    it "should find modules in the search path" do
+        path = %w{/dir/path}
+        Puppet::Module.stubs(:modulepath).returns(path)
+        File.stubs(:directory?).returns(true)
+        mod = Puppet::Module.find("mymod")
+        mod.should be_an_instance_of(Puppet::Module)
+        mod.path.should == "/dir/path/mymod"
+    end
+
+    it "should not search for fully qualified modules" do
+        path = %w{/dir/path}
+        Puppet::Module.expects(:modulepath).never
+        File.expects(:directory?).never
+        Puppet::Module.find("/mymod").should be_nil
+    end
+
+    it "should search for modules in the order specified in the search path" do
+        Puppet[:modulepath] = "/one:/two:/three"
+        Puppet::Module.stubs(:modulepath).returns %w{/one /two /three}
+        File.expects(:directory?).with("/one/mod").returns(false)
+        File.expects(:directory?).with("/two/mod").returns(true)
+        File.expects(:directory?).with("/three/mod").never
+        mod = Puppet::Module.find("mod")
+        mod.path.should == "/two/mod"
+    end
+
+    it "should use a node environment if specified" do
+        Puppet::Module.expects(:modulepath).with("myenv").returns([])
+        Puppet::Module.find("mymod", "myenv")
+    end
+end
+
+describe Puppet::Module, " when searching for templates" do
+    it "should return fully-qualified templates directly" do
+        Puppet::Module.expects(:modulepath).never
+        Puppet::Module.find_template("/my/template").should == "/my/template"
+    end
+
+    it "should return the template from the first found module" do
+        Puppet[:modulepath] = "/one:/two"
+        File.stubs(:directory?).returns(true)
+        Puppet::Module.find_template("mymod/mytemplate").should == "/one/mymod/templates/mytemplate"
+    end
+
+    it "should use the main templatedir if no module is found" do
+        Puppet.settings.expects(:value).with(:templatedir, nil).returns("/my/templates")
+        Puppet::Module.expects(:find).with("mymod", nil).returns(nil)
+        Puppet::Module.find_template("mymod/mytemplate").should == "/my/templates/mymod/mytemplate"
+    end
+
+    it "should return unqualified templates directly in the template dir" do
+        Puppet.settings.expects(:value).with(:templatedir, nil).returns("/my/templates")
+        Puppet::Module.expects(:find).never
+        Puppet::Module.find_template("mytemplate").should == "/my/templates/mytemplate"
+    end
+
+    it "should use the environment templatedir if no module is found and an environment is specified" do
+        Puppet.settings.expects(:value).with(:templatedir, "myenv").returns("/myenv/templates")
+        Puppet::Module.expects(:find).with("mymod", "myenv").returns(nil)
+        Puppet::Module.find_template("mymod/mytemplate", "myenv").should == "/myenv/templates/mymod/mytemplate"
+    end
+
+    it "should use the node environment if specified" do
+        Puppet.settings.expects(:value).with(:modulepath, "myenv").returns("/my/templates")
+        File.stubs(:directory?).returns(true)
+        Puppet::Module.find_template("mymod/envtemplate", "myenv").should == "/my/templates/mymod/templates/envtemplate"
+    end
+
+    after { Puppet.settings.clear }
+end
+
+describe Puppet::Module, " when searching for manifests when no module is found" do
+    before do
+        File.stubs(:find).returns(nil)
+    end
+
+    it "should not look for modules when paths are fully qualified" do
+        Puppet.expects(:value).with(:modulepath).never
+        file = "/fully/qualified/file.pp"
+        Dir.stubs(:glob).with(file).returns([file])
+        Puppet::Module.find_manifests(file)
+    end
+
+    it "should directly return fully qualified files" do
+        file = "/fully/qualified/file.pp"
+        Dir.stubs(:glob).with(file).returns([file])
+        Puppet::Module.find_manifests(file).should == [file]
+    end
+
+    it "should match against provided fully qualified patterns" do
+        pattern = "/fully/qualified/pattern/*"
+        Dir.expects(:glob).with(pattern).returns(%w{my file list})
+        Puppet::Module.find_manifests(pattern).should == %w{my file list}
+    end
+
+    it "should look for files relative to the current directory" do
+        cwd = Dir.getwd
+        Dir.expects(:glob).with("#{cwd}/mymod/init.pp").returns(["#{cwd}/mymod/init.pp"])
+        Puppet::Module.find_manifests("mymod/init.pp").should == ["#{cwd}/mymod/init.pp"]
+    end
+
+    it "should only return files, not directories" do
+        pattern = "/fully/qualified/pattern/*"
+        file = "/my/file"
+        dir = "/my/directory"
+        Dir.expects(:glob).with(pattern).returns([file, dir])
+        FileTest.expects(:directory?).with(file).returns(false)
+        FileTest.expects(:directory?).with(dir).returns(true)
+        Puppet::Module.find_manifests(pattern).should == [file]
+    end
+end
+
+describe Puppet::Module, " when searching for manifests in a found module" do
+    it "should return the manifests from the first found module" do
+        Puppet[:modulepath] = "/one:/two"
+        File.stubs(:directory?).returns(true)
+        Dir.expects(:glob).with("/one/mymod/manifests/init.pp").returns(%w{/one/mymod/manifests/init.pp})
+        Puppet::Module.find_manifests("mymod/init.pp").should == ["/one/mymod/manifests/init.pp"]
+    end
+
+    it "should use the node environment if specified" do
+        Puppet.settings.expects(:value).with(:modulepath, "myenv").returns("/env/modules")
+        File.stubs(:directory?).returns(true)
+        Dir.expects(:glob).with("/env/modules/mymod/manifests/envmanifest.pp").returns(%w{/env/modules/mymod/manifests/envmanifest.pp})
+        Puppet::Module.find_manifests("mymod/envmanifest.pp", :environment => "myenv").should == ["/env/modules/mymod/manifests/envmanifest.pp"]
+    end
+
+    it "should return all manifests matching the glob pattern" do
+        Puppet.settings.expects(:value).with(:modulepath, nil).returns("/my/modules")
+        File.stubs(:directory?).returns(true)
+        Dir.expects(:glob).with("/my/modules/mymod/manifests/yay/*.pp").returns(%w{/one /two})
+        Puppet::Module.find_manifests("mymod/yay/*.pp").should == %w{/one /two}
+    end
+
+    it "should not return directories" do
+        Puppet.settings.expects(:value).with(:modulepath, nil).returns("/my/modules")
+        File.stubs(:directory?).returns(true)
+        Dir.expects(:glob).with("/my/modules/mymod/manifests/yay/*.pp").returns(%w{/one /two})
+        FileTest.expects(:directory?).with("/one").returns false
+        FileTest.expects(:directory?).with("/two").returns true
+        Puppet::Module.find_manifests("mymod/yay/*.pp").should == %w{/one}
+    end
+
+    it "should default to the 'init.pp' file in the manifests directory" do
+        Puppet.settings.expects(:value).with(:modulepath, nil).returns("/my/modules")
+        File.stubs(:directory?).returns(true)
+        Dir.expects(:glob).with("/my/modules/mymod/manifests/init.pp").returns(%w{my manifest})
+        Puppet::Module.find_manifests("mymod").should == %w{my manifest}
+    end
+
+    after { Puppet.settings.clear }
+end
+
+describe Puppet::Module, " when returning files" do
+    it "should return the path to the module's 'files' directory" do
+        mod = Puppet::Module.send(:new, "mymod", "/my/mod")
+        mod.files.should == "/my/mod/files"
+    end
+end
diff --git a/spec/unit/network/client.rb b/spec/unit/network/client.rb
new file mode 100644
index 0000000..bc41efb
--- /dev/null
+++ b/spec/unit/network/client.rb
@@ -0,0 +1,43 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2008-3-24.
+#  Copyright (c) 2008. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/network/client'
+
+describe Puppet::Network::Client do
+    before do
+        Puppet::Network::HttpPool.stubs(:cert_setup)
+    end
+    describe "when keep-alive is enabled" do
+        before do
+            Puppet::Network::HttpPool.stubs(:keep_alive?).returns true
+        end
+        it "should start the http client up on creation" do
+            http = mock 'http'
+            http.stub_everything
+            http.expects(:start)
+            Net::HTTP.stubs(:new).returns http
+
+            # Pick a random subclass...
+            Puppet::Network::Client.master.new :Server => Puppet[:server]
+        end
+    end
+
+    describe "when keep-alive is disabled" do
+        before do
+            Puppet::Network::HttpPool.stubs(:keep_alive?).returns false
+        end
+        it "should not start the http client up on creation" do
+            http = mock 'http'
+            http.stub_everything
+            http.expects(:start).never
+            Net::HTTP.stubs(:new).returns http
+
+            # Pick a random subclass...
+            Puppet::Network::Client.master.new :Server => Puppet[:server]
+        end
+    end
+end
diff --git a/spec/unit/network/client/master.rb b/spec/unit/network/client/master.rb
new file mode 100755
index 0000000..c0ad756
--- /dev/null
+++ b/spec/unit/network/client/master.rb
@@ -0,0 +1,340 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-11-12.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/network/client/master'
+
+describe Puppet::Network::Client::Master, " when retrieving the catalog" do
+    before do
+        @master = mock 'master'
+        @client = Puppet::Network::Client.master.new(
+            :Master => @master
+        )
+        @facts = {"one" => "two", "three" => "four"}
+    end
+
+    it "should initialize the metadata store" do
+        @client.class.stubs(:facts).returns(@facts)
+        @client.expects(:dostorage)
+        @master.stubs(:getconfig).returns(nil)
+        @client.getconfig
+    end
+
+    it "should collect facts to use for catalog retrieval" do
+        @client.stubs(:dostorage)
+        @client.class.expects(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns(nil)
+        @client.getconfig
+    end
+
+    it "should fail if no facts could be collected" do
+        @client.stubs(:dostorage)
+        @client.class.expects(:facts).returns({})
+        @master.stubs(:getconfig).returns(nil)
+        proc { @client.getconfig }.should raise_error(Puppet::Network::ClientError)
+    end
+
+    it "should retrieve plugins if :pluginsync is enabled" do
+        file = "/path/to/cachefile"
+        @client.stubs(:cachefile).returns(file)
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        Puppet.settings.expects(:value).with(:pluginsync).returns(true)
+        @client.expects(:getplugins)
+        @client.stubs(:get_actual_config).returns(nil)
+        FileTest.stubs(:exist?).with(file).returns(true)
+        @client.stubs(:use_cached_config).returns(true)
+        @client.class.stubs(:facts).returns(@facts)
+        @client.getconfig
+    end
+
+    it "should use the cached catalog if no catalog could be retrieved" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).raises(ArgumentError.new("whev"))
+        @client.expects(:use_cached_config).with(true)
+        @client.getconfig
+    end
+
+    it "should load the retrieved catalog using YAML" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        config = mock 'config'
+        YAML.expects(:load).with("myconfig").returns(config)
+
+        @client.stubs(:setclasses)
+
+        config.stubs(:classes)
+        config.stubs(:to_catalog).returns(config)
+        config.stubs(:host_config=)
+        config.stubs(:from_cache).returns(true)
+
+        @client.getconfig
+    end
+
+    it "should use the cached catalog if the retrieved catalog cannot be converted from YAML" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        YAML.expects(:load).with("myconfig").raises(ArgumentError)
+
+        @client.expects(:use_cached_config).with(true)
+
+        @client.getconfig
+    end
+
+    it "should set the classes.txt file with the classes listed in the retrieved catalog" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        config = mock 'config'
+        YAML.expects(:load).with("myconfig").returns(config)
+
+        config.expects(:classes).returns(:myclasses)
+        @client.expects(:setclasses).with(:myclasses)
+
+        config.stubs(:to_catalog).returns(config)
+        config.stubs(:host_config=)
+        config.stubs(:from_cache).returns(true)
+
+        @client.getconfig
+    end
+
+    it "should convert the retrieved catalog to a RAL catalog" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        yamlconfig = mock 'yaml config'
+        YAML.stubs(:load).returns(yamlconfig)
+
+        @client.stubs(:setclasses)
+
+        config = mock 'config'
+
+        yamlconfig.stubs(:classes)
+        yamlconfig.expects(:to_catalog).returns(config)
+
+        config.stubs(:host_config=)
+        config.stubs(:from_cache).returns(true)
+
+        @client.getconfig
+    end
+
+    it "should use the cached catalog if the retrieved catalog cannot be converted to a RAL catalog" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        yamlconfig = mock 'yaml config'
+        YAML.stubs(:load).returns(yamlconfig)
+
+        @client.stubs(:setclasses)
+
+        config = mock 'config'
+
+        yamlconfig.stubs(:classes)
+        yamlconfig.expects(:to_catalog).raises(ArgumentError)
+
+        @client.expects(:use_cached_config).with(true)
+
+        @client.getconfig
+    end
+
+    it "should clear the failed catalog if using the cached catalog after failing to instantiate the retrieved catalog" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        yamlconfig = mock 'yaml config'
+        YAML.stubs(:load).returns(yamlconfig)
+
+        @client.stubs(:setclasses)
+
+        config = mock 'config'
+
+        yamlconfig.stubs(:classes)
+        yamlconfig.stubs(:to_catalog).raises(ArgumentError)
+
+        @client.stubs(:use_cached_config).with(true)
+
+        @client.expects(:clear)
+
+        @client.getconfig
+    end
+
+    it "should cache the retrieved yaml catalog if it is not from the cache and is valid" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        yamlconfig = mock 'yaml config'
+        YAML.stubs(:load).returns(yamlconfig)
+
+        @client.stubs(:setclasses)
+
+        config = mock 'config'
+
+        yamlconfig.stubs(:classes)
+        yamlconfig.expects(:to_catalog).returns(config)
+
+        config.stubs(:host_config=)
+
+        config.expects(:from_cache).returns(false)
+
+        @client.expects(:cache).with("myconfig")
+
+        @client.getconfig
+    end
+
+    it "should mark the catalog as a host catalog" do
+        @client.stubs(:dostorage)
+        @client.class.stubs(:facts).returns(@facts)
+        @master.stubs(:getconfig).returns("myconfig")
+
+        yamlconfig = mock 'yaml config'
+        YAML.stubs(:load).returns(yamlconfig)
+
+        @client.stubs(:setclasses)
+
+        config = mock 'config'
+
+        yamlconfig.stubs(:classes)
+        yamlconfig.expects(:to_catalog).returns(config)
+
+        config.stubs(:from_cache).returns(true)
+
+        config.expects(:host_config=).with(true)
+
+        @client.getconfig
+    end
+end
+
+describe Puppet::Network::Client::Master, " when using the cached catalog" do
+    before do
+        @master = mock 'master'
+        @client = Puppet::Network::Client.master.new(
+            :Master => @master
+        )
+        @facts = {"one" => "two", "three" => "four"}
+    end
+
+    it "should return do nothing and true if there is already an in-memory catalog" do
+        @client.catalog = :whatever
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config.should be_true
+        end
+    end
+
+    it "should return do nothing and false if it has been told there is a failure and :nocacheonfailure is enabled" do
+        Puppet.settings.expects(:value).with(:usecacheonfailure).returns(false)
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config(true).should be_false
+        end
+    end
+
+    it "should return false if no cached catalog can be found" do
+        @client.expects(:retrievecache).returns(nil)
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config().should be_false
+        end
+    end
+
+    it "should return false if the cached catalog cannot be instantiated" do
+        YAML.expects(:load).raises(ArgumentError)
+        @client.expects(:retrievecache).returns("whatever")
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config().should be_false
+        end
+    end
+
+    it "should warn if the cached catalog cannot be instantiated" do
+        YAML.stubs(:load).raises(ArgumentError)
+        @client.stubs(:retrievecache).returns("whatever")
+        Puppet.expects(:warning).with { |m| m.include?("Could not load cache") }
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config().should be_false
+        end
+    end
+
+    it "should clear the client if the cached catalog cannot be instantiated" do
+        YAML.stubs(:load).raises(ArgumentError)
+        @client.stubs(:retrievecache).returns("whatever")
+        @client.expects(:clear)
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config().should be_false
+        end
+    end
+
+    it "should return true if the cached catalog can be instantiated" do
+        config = mock 'config'
+        YAML.stubs(:load).returns(config)
+
+        ral_config = mock 'ral config'
+        ral_config.stubs(:from_cache=)
+        ral_config.stubs(:host_config=)
+        config.expects(:to_catalog).returns(ral_config)
+
+        @client.stubs(:retrievecache).returns("whatever")
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config().should be_true
+        end
+    end
+
+    it "should set the catalog instance variable if the cached catalog can be instantiated" do
+        config = mock 'config'
+        YAML.stubs(:load).returns(config)
+
+        ral_config = mock 'ral config'
+        ral_config.stubs(:from_cache=)
+        ral_config.stubs(:host_config=)
+        config.expects(:to_catalog).returns(ral_config)
+
+        @client.stubs(:retrievecache).returns("whatever")
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config()
+        end
+
+        @client.catalog.should equal(ral_config)
+    end
+
+    it "should mark the catalog as a host_config if valid" do
+        config = mock 'config'
+        YAML.stubs(:load).returns(config)
+
+        ral_config = mock 'ral config'
+        ral_config.stubs(:from_cache=)
+        ral_config.expects(:host_config=).with(true)
+        config.expects(:to_catalog).returns(ral_config)
+
+        @client.stubs(:retrievecache).returns("whatever")
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config()
+        end
+
+        @client.catalog.should equal(ral_config)
+    end
+
+    it "should mark the catalog as from the cache if valid" do
+        config = mock 'config'
+        YAML.stubs(:load).returns(config)
+
+        ral_config = mock 'ral config'
+        ral_config.expects(:from_cache=).with(true)
+        ral_config.stubs(:host_config=)
+        config.expects(:to_catalog).returns(ral_config)
+
+        @client.stubs(:retrievecache).returns("whatever")
+        Puppet::Network::Client::Master.publicize_methods :use_cached_config do
+            @client.use_cached_config()
+        end
+
+        @client.catalog.should equal(ral_config)
+    end
+end
diff --git a/spec/unit/network/http.rb b/spec/unit/network/http.rb
new file mode 100644
index 0000000..79a0a88
--- /dev/null
+++ b/spec/unit/network/http.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+#
+#  Created by Rick Bradley on 2007-10-03.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/network/http'
+
+describe Puppet::Network::HTTP do
+    it "should return the webrick HTTP server class when asked for a webrick server" do
+        Puppet::Network::HTTP.server_class_by_type(:webrick).should be(Puppet::Network::HTTP::WEBrick)
+    end
+    
+    if Puppet.features.mongrel?
+        it "should return the mongrel HTTP server class when asked for a mongrel server" do
+            Puppet::Network::HTTP.server_class_by_type(:mongrel).should be(Puppet::Network::HTTP::Mongrel)
+        end
+    end
+    
+    it "should fail to return the mongrel HTTP server class if mongrel is not available " do
+        Puppet.features.expects(:mongrel?).returns(false)
+        Proc.new { Puppet::Network::HTTP.server_class_by_type(:mongrel) }.should raise_error(ArgumentError)
+    end
+    
+    it "should return an error when asked for an unknown server" do
+        Proc.new { Puppet::Network::HTTP.server_class_by_type :foo }.should raise_error(ArgumentError)
+    end
+end
diff --git a/spec/unit/network/http/mongrel.rb b/spec/unit/network/http/mongrel.rb
new file mode 100644
index 0000000..ccfca2f
--- /dev/null
+++ b/spec/unit/network/http/mongrel.rb
@@ -0,0 +1,113 @@
+#!/usr/bin/env ruby
+#
+#  Created by Rick Bradley on 2007-10-15.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/network/http'
+
+describe Puppet::Network::HTTP::Mongrel, "after initializing" do
+    confine "Mongrel is not available" => Puppet.features.mongrel?
+    
+    it "should not be listening" do
+        Puppet::Network::HTTP::Mongrel.new.should_not be_listening
+    end
+end
+
+describe Puppet::Network::HTTP::Mongrel, "when turning on listening" do
+    confine "Mongrel is not available" => Puppet.features.mongrel?
+
+    before do
+        @server = Puppet::Network::HTTP::Mongrel.new
+        @mock_mongrel = mock('mongrel')
+        @mock_mongrel.stubs(:run)
+        @mock_mongrel.stubs(:register)
+        Mongrel::HttpServer.stubs(:new).returns(@mock_mongrel)
+        @listen_params = { :address => "127.0.0.1", :port => 31337, :handlers => [ :node, :catalog ], :protocols => [ :rest ] }
+    end
+    
+    it "should fail if already listening" do
+        @server.listen(@listen_params)
+        Proc.new { @server.listen(@listen_params) }.should raise_error(RuntimeError)
+    end
+    
+    it "should require at least one handler" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :handlers == k}) }.should raise_error(ArgumentError)
+    end
+    
+    it "should require at least one protocol" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :protocols == k}) }.should raise_error(ArgumentError)
+    end
+    
+    it "should require a listening address to be specified" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :address == k})}.should raise_error(ArgumentError)
+    end
+    
+    it "should require a listening port to be specified" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :port == k})}.should raise_error(ArgumentError)
+    end
+    
+    it "should order a mongrel server to start" do
+        @mock_mongrel.expects(:run)
+        @server.listen(@listen_params)
+    end
+    
+    it "should tell mongrel to listen on the specified address and port" do
+        Mongrel::HttpServer.expects(:new).with("127.0.0.1", 31337).returns(@mock_mongrel)
+        @server.listen(@listen_params)
+    end
+    
+    it "should be listening" do
+        Mongrel::HttpServer.expects(:new).returns(@mock_mongrel)
+        @server.listen(@listen_params)
+        @server.should be_listening
+    end
+
+    it "should instantiate a handler for each protocol+handler pair to configure web server routing" do
+        @listen_params[:protocols].each do |protocol|
+            @listen_params[:handlers].each do |handler|
+                @mock_mongrel.expects(:register)
+            end
+        end
+        @server.listen(@listen_params)        
+    end
+    
+    it "should use a Mongrel + REST class to configure Mongrel when REST services are requested" do
+        @server.expects(:class_for_protocol).with(:rest).at_least_once.returns(Puppet::Network::HTTP::MongrelREST)
+        @server.listen(@listen_params)
+    end
+    
+    it "should fail if services from an unknown protocol are requested" do
+        Proc.new { @server.listen(@listen_params.merge(:protocols => [ :foo ]))}.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Network::HTTP::Mongrel, "when turning off listening" do
+    confine "Mongrel is not available" => Puppet.features.mongrel?
+    
+    before do
+        @mock_mongrel = mock('mongrel httpserver')
+        @mock_mongrel.stubs(:run)
+        @mock_mongrel.stubs(:register)
+        Mongrel::HttpServer.stubs(:new).returns(@mock_mongrel)
+        @server = Puppet::Network::HTTP::Mongrel.new        
+        @listen_params = { :address => "127.0.0.1", :port => 31337, :handlers => [ :node, :catalog ], :protocols => [ :rest ] }
+    end
+    
+    it "should fail unless listening" do
+        Proc.new { @server.unlisten }.should raise_error(RuntimeError)
+    end
+    
+    it "should order mongrel server to stop" do
+        @server.listen(@listen_params)
+        @mock_mongrel.expects(:stop)
+        @server.unlisten
+    end
+    
+    it "should not be listening" do
+        @server.listen(@listen_params)
+        @mock_mongrel.stubs(:stop)
+        @server.unlisten
+        @server.should_not be_listening
+    end
+end
diff --git a/spec/unit/network/http/mongrel/rest.rb b/spec/unit/network/http/mongrel/rest.rb
new file mode 100644
index 0000000..b483bbd
--- /dev/null
+++ b/spec/unit/network/http/mongrel/rest.rb
@@ -0,0 +1,269 @@
+require File.dirname(__FILE__) + '/../../../../spec_helper'
+require 'puppet/network/http'
+
+describe Puppet::Network::HTTP::MongrelREST, "when initializing" do
+    confine "Mongrel is not available" => Puppet.features.mongrel?
+    
+    before do
+        @mock_mongrel = mock('Mongrel server')
+        @mock_mongrel.stubs(:register)
+        @mock_model = mock('indirected model')
+        Puppet::Indirector::Indirection.stubs(:model).with(:foo).returns(@mock_model)
+        @params = { :server => @mock_mongrel, :handler => :foo }
+    end
+    
+    it "should require access to a Mongrel server" do
+        Proc.new { Puppet::Network::HTTP::MongrelREST.new(@params.delete_if {|k,v| :server == k })}.should raise_error(ArgumentError)
+    end
+    
+    it "should require an indirection name" do
+        Proc.new { Puppet::Network::HTTP::MongrelREST.new(@params.delete_if {|k,v| :handler == k })}.should raise_error(ArgumentError)        
+    end
+    
+    it "should look up the indirection model from the indirection name" do
+        Puppet::Indirector::Indirection.expects(:model).with(:foo).returns(@mock_model)
+        Puppet::Network::HTTP::MongrelREST.new(@params)
+    end
+    
+    it "should fail if the indirection is not known" do
+        Puppet::Indirector::Indirection.expects(:model).with(:foo).returns(nil)
+        Proc.new { Puppet::Network::HTTP::MongrelREST.new(@params) }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Network::HTTP::MongrelREST, "when receiving a request" do
+    confine "Mongrel is not available" => Puppet.features.mongrel?
+    
+    before do
+        @mock_request = stub('mongrel http request')
+        @mock_head = stub('response head')
+        @mock_body = stub('response body', :write => true)
+        @mock_response = stub('mongrel http response')
+        @mock_response.stubs(:start).yields(@mock_head, @mock_body)
+        @mock_model_class = stub('indirected model class')
+        @mock_mongrel = stub('mongrel http server', :register => true)
+        Puppet::Indirector::Indirection.stubs(:model).with(:foo).returns(@mock_model_class)
+        @handler = Puppet::Network::HTTP::MongrelREST.new(:server => @mock_mongrel, :handler => :foo)
+    end
+    
+    def setup_find_request(params = {})
+        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'GET', 
+                                                Mongrel::Const::REQUEST_PATH => '/foo/key',
+                                                'QUERY_STRING' => ''}.merge(params))
+        @mock_model_class.stubs(:find)
+    end
+    
+    def setup_search_request(params = {})
+        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'GET', 
+                                                Mongrel::Const::REQUEST_PATH => '/foos',
+                                                'QUERY_STRING' => '' }.merge(params))
+        @mock_model_class.stubs(:search).returns([])        
+    end
+    
+    def setup_destroy_request(params = {})
+        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'DELETE', 
+                                                Mongrel::Const::REQUEST_PATH => '/foo/key',
+                                                'QUERY_STRING' => '' }.merge(params))
+        @mock_model_class.stubs(:destroy)
+    end
+    
+    def setup_save_request(params = {})
+        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'PUT', 
+                                                Mongrel::Const::REQUEST_PATH => '/foo',
+                                                'QUERY_STRING' => '' }.merge(params))
+        @mock_request.stubs(:body).returns('this is a fake request body')
+        @mock_model_instance = stub('indirected model instance', :save => true)
+        @mock_model_class.stubs(:from_yaml).returns(@mock_model_instance)
+    end
+    
+    def setup_bad_request
+        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'POST', Mongrel::Const::REQUEST_PATH => '/foos'})        
+    end
+
+    it "should call the model find method if the request represents a singular HTTP GET" do
+        setup_find_request
+        @mock_model_class.expects(:find).with('key', {})
+        @handler.process(@mock_request, @mock_response)
+    end
+
+    it "should call the model search method if the request represents a plural HTTP GET" do
+        setup_search_request
+        @mock_model_class.expects(:search).with({}).returns([])
+        @handler.process(@mock_request, @mock_response)
+    end
+    
+    it "should call the model destroy method if the request represents an HTTP DELETE" do
+        setup_destroy_request
+        @mock_model_class.expects(:destroy).with('key', {})
+        @handler.process(@mock_request, @mock_response)
+    end
+
+    it "should call the model save method if the request represents an HTTP PUT" do
+        setup_save_request
+        @mock_model_instance.expects(:save)
+        @handler.process(@mock_request, @mock_response)
+    end
+    
+    it "should fail if the HTTP method isn't supported" do
+        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'POST', Mongrel::Const::REQUEST_PATH => '/foo'})
+        @mock_response.expects(:start).with(404)
+        @handler.process(@mock_request, @mock_response)
+    end
+    
+    it "should fail if the request's pluralization is wrong" do
+        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'DELETE', Mongrel::Const::REQUEST_PATH => '/foos/key'})
+        @mock_response.expects(:start).with(404)
+        @handler.process(@mock_request, @mock_response)
+
+        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'PUT', Mongrel::Const::REQUEST_PATH => '/foos/key'})
+        @mock_response.expects(:start).with(404)
+        @handler.process(@mock_request, @mock_response)
+    end
+
+    it "should fail if the request is for an unknown path" do
+        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'GET', 
+                                                Mongrel::Const::REQUEST_PATH => '/bar/key',
+                                                'QUERY_STRING' => '' })
+        @mock_response.expects(:start).with(404)
+        @handler.process(@mock_request, @mock_response)
+    end
+    
+    
+    describe "when finding a model instance" do |variable|
+        it "should fail to find model if key is not specified" do
+            @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'GET', Mongrel::Const::REQUEST_PATH => '/foo'})
+            @mock_response.expects(:start).with(404)
+            @handler.process(@mock_request, @mock_response)
+        end
+
+        it "should pass HTTP request parameters to model find" do
+            setup_find_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
+            @mock_model_class.expects(:find).with do |key, args|
+                key == 'key' and args['foo'] == 'baz' and args['bar'] == 'xyzzy'
+            end
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should generate a 200 response when a model find call succeeds" do
+            setup_find_request
+            @mock_response.expects(:start).with(200)
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should return a serialized object when a model find call succeeds" do
+            setup_find_request
+            @mock_model_instance = stub('model instance')
+            @mock_model_instance.expects(:to_yaml)
+            @mock_model_class.stubs(:find).returns(@mock_model_instance)
+            @handler.process(@mock_request, @mock_response)                  
+        end
+        
+        it "should serialize a controller exception when an exception is thrown by find" do
+           setup_find_request
+           @mock_model_class.expects(:find).raises(ArgumentError) 
+           @mock_response.expects(:start).with(404)
+           @handler.process(@mock_request, @mock_response)        
+        end
+    end
+
+    describe "when destroying a model instance" do |variable|
+        it "should fail to destroy model if key is not specified" do
+            @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'DELETE', Mongrel::Const::REQUEST_PATH => '/foo'})
+            @mock_response.expects(:start).with(404)
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should pass HTTP request parameters to model destroy" do
+            setup_destroy_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
+            @mock_model_class.expects(:destroy).with do |key, args|
+                key == 'key' and args['foo'] == 'baz' and args['bar'] == 'xyzzy'
+            end
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should generate a 200 response when a model destroy call succeeds" do
+            setup_destroy_request
+            @mock_response.expects(:start).with(200)
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should return a serialized success result when a model destroy call succeeds" do
+            setup_destroy_request
+            @mock_model_class.stubs(:destroy).returns(true)
+            @mock_body.expects(:write).with("--- true\n")
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should serialize a controller exception when an exception is thrown by destroy" do
+            setup_destroy_request
+            @mock_model_class.expects(:destroy).raises(ArgumentError) 
+            @mock_response.expects(:start).with(404)
+            @handler.process(@mock_request, @mock_response)                 
+        end
+    end
+    
+    describe "when saving a model instance" do |variable|    
+        it "should fail to save model if data is not specified" do
+            @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'PUT', Mongrel::Const::REQUEST_PATH => '/foo'})
+            @mock_request.stubs(:body).returns('')
+            @mock_response.expects(:start).with(404)
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should generate a 200 response when a model save call succeeds" do
+            setup_save_request
+            @mock_response.expects(:start).with(200)
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should return a serialized object when a model save call succeeds" do
+            setup_save_request
+            @mock_model_instance.stubs(:save).returns(@mock_model_instance)
+            @mock_model_instance.expects(:to_yaml).returns('foo')
+            @handler.process(@mock_request, @mock_response)        
+        end
+        
+        it "should serialize a controller exception when an exception is thrown by save" do
+            setup_save_request
+            @mock_model_instance.expects(:save).raises(ArgumentError) 
+            @mock_response.expects(:start).with(404)
+            @handler.process(@mock_request, @mock_response)                         
+        end
+    end
+    
+    describe "when searching for model instances" do |variable|
+        it "should pass HTTP request parameters to model search" do
+            setup_search_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
+            @mock_model_class.expects(:search).with do |args|
+                args['foo'] == 'baz' and args['bar'] == 'xyzzy'
+            end.returns([])
+            @handler.process(@mock_request, @mock_response)
+        end      
+
+        it "should generate a 200 response when a model search call succeeds" do
+            setup_search_request
+            @mock_response.expects(:start).with(200)
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should return a list of serialized objects when a model search call succeeds" do
+            setup_search_request
+            mock_matches = [1..5].collect {|i| mock("model instance #{i}", :to_yaml => "model instance #{i}") }
+            @mock_model_class.stubs(:search).returns(mock_matches)
+            @handler.process(@mock_request, @mock_response)                          
+        end
+
+        it "should serialize a controller exception when an exception is thrown by search" do
+            setup_search_request
+            @mock_model_class.expects(:search).raises(ArgumentError) 
+            @mock_response.expects(:start).with(404)
+            @handler.process(@mock_request, @mock_response)                
+        end
+    end    
+    
+    it "should serialize a controller exception if the request fails" do
+        setup_bad_request     
+        @mock_response.expects(:start).with(404)
+        @handler.process(@mock_request, @mock_response)        
+    end
+end
diff --git a/examples/etc/otherfile b/spec/unit/network/http/mongrel/xmlrpc.rb
similarity index 100%
copy from examples/etc/otherfile
copy to spec/unit/network/http/mongrel/xmlrpc.rb
diff --git a/spec/unit/network/http/webrick.rb b/spec/unit/network/http/webrick.rb
new file mode 100644
index 0000000..05ed2f0
--- /dev/null
+++ b/spec/unit/network/http/webrick.rb
@@ -0,0 +1,126 @@
+#!/usr/bin/env ruby
+#
+#  Created by Rick Bradley on 2007-10-15.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/network/http'
+
+describe Puppet::Network::HTTP::WEBrick, "after initializing" do
+    it "should not be listening" do
+        Puppet::Network::HTTP::WEBrick.new.should_not be_listening
+    end
+end
+
+describe Puppet::Network::HTTP::WEBrick, "when turning on listening" do
+    before do
+        @mock_webrick = stub('webrick', :[] => {})
+        [:mount, :start, :shutdown].each {|meth| @mock_webrick.stubs(meth)}        
+        WEBrick::HTTPServer.stubs(:new).returns(@mock_webrick)
+        @server = Puppet::Network::HTTP::WEBrick.new
+        @listen_params = { :address => "127.0.0.1", :port => 31337, :handlers => [ :node, :catalog ], :protocols => [ :rest ] }
+    end
+    
+    it "should fail if already listening" do
+        @server.listen(@listen_params)
+        Proc.new { @server.listen(@listen_params) }.should raise_error(RuntimeError)
+    end
+    
+    it "should require at least one handler" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :handlers == k}) }.should raise_error(ArgumentError)
+    end
+    
+    it "should require at least one protocol" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :protocols == k}) }.should raise_error(ArgumentError)
+    end
+
+    it "should require a listening address to be specified" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :address == k})}.should raise_error(ArgumentError)
+    end
+    
+    it "should require a listening port to be specified" do
+        Proc.new { @server.listen(@listen_params.delete_if {|k,v| :port == k})}.should raise_error(ArgumentError)        
+    end
+
+    it "should order a webrick server to start" do
+        @mock_webrick.expects(:start)
+        @server.listen(@listen_params)
+    end
+    
+    it "should tell webrick to listen on the specified address and port" do
+        WEBrick::HTTPServer.expects(:new).with {|args|
+            args[:Port] == 31337 and args[:BindAddress] == "127.0.0.1"
+        }.returns(@mock_webrick)
+        @server.listen(@listen_params)
+    end
+    
+    it "should be listening" do
+        @server.listen(@listen_params)
+        @server.should be_listening
+    end
+    
+    it "should instantiate a handler for each protocol+handler pair to configure web server routing" do
+        @listen_params[:protocols].each do |protocol|
+            mock_handler = mock("handler instance for [#{protocol}]")
+            mock_handler_class = mock("handler class for [#{protocol}]")
+            @listen_params[:handlers].each do |handler|
+                @mock_webrick.expects(:mount)
+            end
+        end
+        @server.listen(@listen_params)        
+    end
+
+    it "should use a WEBrick + REST class to configure WEBrick when REST services are requested" do
+        Puppet::Network::HTTP::WEBrick.expects(:class_for_protocol).with(:rest).at_least_once
+        @server.listen(@listen_params.merge(:protocols => [:rest]))
+    end
+    
+    it "should fail if services from an unknown protocol are requested" do
+        Proc.new { @server.listen(@listen_params.merge(:protocols => [ :foo ]))}.should raise_error
+    end
+end
+
+
+describe Puppet::Network::HTTP::WEBrick, "when looking up the class to handle a protocol" do
+  it "should require a protocol" do
+    lambda { Puppet::Network::HTTP::WEBrick.class_for_protocol }.should raise_error(ArgumentError)
+  end
+  
+  it "should accept a protocol" do
+    lambda { Puppet::Network::HTTP::WEBrick.class_for_protocol("bob") }.should_not raise_error(ArgumentError)    
+  end
+  
+  it "should use a WEBrick + REST class when a REST protocol is specified" do
+    Puppet::Network::HTTP::WEBrick.class_for_protocol("rest").should == Puppet::Network::HTTP::WEBrickREST
+  end
+  
+  it "should fail when an unknown protocol is specified" do
+    lambda { Puppet::Network::HTTP::WEBrick.class_for_protocol("abcdefg") }.should raise_error
+  end
+end
+
+describe Puppet::Network::HTTP::WEBrick, "when turning off listening" do
+    before do
+        @mock_webrick = stub('webrick', :[] => {})
+        [:mount, :start, :shutdown].each {|meth| @mock_webrick.stubs(meth)}
+        WEBrick::HTTPServer.stubs(:new).returns(@mock_webrick)
+        @server = Puppet::Network::HTTP::WEBrick.new        
+        @listen_params = { :address => "127.0.0.1", :port => 31337, :handlers => [ :node, :catalog ], :protocols => [ :rest ] }
+    end
+    
+    it "should fail unless listening" do
+        Proc.new { @server.unlisten }.should raise_error(RuntimeError)
+    end
+    
+    it "should order webrick server to stop" do
+        @mock_webrick.expects(:shutdown)
+        @server.listen(@listen_params)
+        @server.unlisten
+    end
+    
+    it "should no longer be listening" do
+        @server.listen(@listen_params)
+        @server.unlisten
+        @server.should_not be_listening
+    end
+end
diff --git a/spec/unit/network/http/webrick/rest.rb b/spec/unit/network/http/webrick/rest.rb
new file mode 100644
index 0000000..b7bd338
--- /dev/null
+++ b/spec/unit/network/http/webrick/rest.rb
@@ -0,0 +1,271 @@
+require File.dirname(__FILE__) + '/../../../../spec_helper'
+require 'puppet/network/http'
+
+describe Puppet::Network::HTTP::WEBrickREST, "when initializing" do
+    before do
+        @mock_webrick = stub('WEBrick server', :mount => true, :[] => {})
+        @mock_model = mock('indirected model')
+        Puppet::Indirector::Indirection.stubs(:model).returns(@mock_model)
+        @params = [ @mock_webrick, :foo ]
+    end
+    
+    it "should require access to a WEBrick server" do
+        Proc.new { 
+            @params[0] = nil
+            Puppet::Network::HTTP::WEBrickREST.new(*@params)
+        }.should raise_error(ArgumentError)
+    end
+    
+    it "should require an indirection name" do
+        Proc.new { Puppet::Network::HTTP::WEBrickREST.new(@params.first) }.should raise_error(ArgumentError)        
+    end
+    
+    it "should look up the indirection model from the indirection name" do
+        Puppet::Indirector::Indirection.expects(:model).returns(@mock_model)
+        Puppet::Network::HTTP::WEBrickREST.new(*@params)
+    end
+    
+    it "should fail if the indirection is not known" do
+        Puppet::Indirector::Indirection.expects(:model).returns(nil)
+        Proc.new { Puppet::Network::HTTP::WEBrickREST.new(*@params) }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Network::HTTP::WEBrickREST, "when receiving a request" do
+    before do
+        @mock_request     = stub('webrick http request', :query => {})
+        @mock_response    = stub('webrick http response', :status= => true, :body= => true)
+        @mock_model_class = stub('indirected model class')
+        @mock_webrick     = stub('webrick http server', :mount => true, :[] => {})
+        Puppet::Indirector::Indirection.stubs(:model).with(:foo).returns(@mock_model_class)
+        @handler = Puppet::Network::HTTP::WEBrickREST.new(@mock_webrick, :foo)
+    end
+
+    def setup_find_request
+        @mock_request.stubs(:request_method).returns('GET')
+        @mock_request.stubs(:path).returns('/foo/key')
+        @mock_model_class.stubs(:find)
+    end
+    
+    def setup_search_request
+        @mock_request.stubs(:request_method).returns('GET')
+        @mock_request.stubs(:path).returns('/foos')
+        @mock_model_class.stubs(:search).returns([])
+    end
+    
+    def setup_destroy_request
+        @mock_request.stubs(:request_method).returns('DELETE')
+        @mock_request.stubs(:path).returns('/foo/key')
+        @mock_model_class.stubs(:destroy)
+    end
+    
+    def setup_save_request
+        @mock_request.stubs(:request_method).returns('PUT')
+        @mock_request.stubs(:path).returns('/foo')
+        @mock_request.stubs(:body).returns('This is a fake request body')
+        @mock_model_instance = stub('indirected model instance', :save => true)
+        @mock_model_class.stubs(:from_yaml).returns(@mock_model_instance)
+    end
+    
+    def setup_bad_request
+        @mock_request.stubs(:request_method).returns('POST')
+        @mock_request.stubs(:path).returns('/foos')
+    end
+    
+    
+    it "should call the model find method if the request represents a singular HTTP GET" do
+        setup_find_request
+        @mock_model_class.expects(:find).with('key', {})
+        @handler.service(@mock_request, @mock_response)
+    end
+
+    it "should call the model search method if the request represents a plural HTTP GET" do
+        setup_search_request
+        @mock_model_class.expects(:search).returns([])
+        @handler.service(@mock_request, @mock_response)
+    end
+    
+    it "should call the model destroy method if the request represents an HTTP DELETE" do
+        setup_destroy_request
+        @mock_model_class.expects(:destroy).with('key', {})
+        @handler.service(@mock_request, @mock_response)
+    end
+
+    it "should call the model save method if the request represents an HTTP PUT" do
+        setup_save_request
+        @mock_model_instance.expects(:save)
+        @handler.service(@mock_request, @mock_response)
+    end
+    
+    it "should fail if the HTTP method isn't supported" do
+        @mock_request.stubs(:request_method).returns('POST')
+        @mock_request.stubs(:path).returns('/foo')
+        @mock_response.expects(:status=).with(404)
+        @handler.process(@mock_request, @mock_response)            
+    end
+    
+    it "should fail if delete request's pluralization is wrong" do
+        @mock_request.stubs(:request_method).returns('DELETE')
+        @mock_request.stubs(:path).returns('/foos/key')
+        @mock_response.expects(:status=).with(404)
+        @handler.process(@mock_request, @mock_response)            
+    end
+
+    it "should fail if put request's pluralization is wrong" do 
+        @mock_request.stubs(:request_method).returns('PUT')
+        @mock_request.stubs(:path).returns('/foos/key')
+        @mock_response.expects(:status=).with(404)
+        @handler.process(@mock_request, @mock_response)            
+    end
+
+    it "should fail if the request is for an unknown path" do
+        @mock_request.stubs(:request_method).returns('GET')
+        @mock_request.stubs(:path).returns('/bar/key')
+        @mock_response.expects(:status=).with(404)
+        @handler.process(@mock_request, @mock_response)            
+    end
+
+    describe "when finding a model instance" do |variable|
+        it "should fail to find model if key is not specified" do
+            @mock_request.stubs(:request_method).returns('GET')
+            @mock_request.stubs(:path).returns('/foo')
+            @mock_response.expects(:status=).with(404)
+            @handler.process(@mock_request, @mock_response)            
+        end
+        
+        it "should pass HTTP request parameters to model find" do
+            setup_find_request
+            @mock_request.stubs(:query).returns(:foo => :baz, :bar => :xyzzy)
+            @mock_model_class.expects(:find).with do |key, args|
+                key == 'key' and args[:foo] == :baz and args[:bar] == :xyzzy
+            end
+            @handler.service(@mock_request, @mock_response)
+        end
+        
+        it "should generate a 200 response when a model find call succeeds" do
+            setup_find_request
+            @mock_response.expects(:status=).with(200)
+            @handler.process(@mock_request, @mock_response)      
+        end
+        
+        it "should return a serialized object when a model find call succeeds" do
+            setup_find_request
+            @mock_model_instance = stub('model instance')
+            @mock_model_instance.expects(:to_yaml)
+            @mock_model_class.stubs(:find).returns(@mock_model_instance)
+            @handler.process(@mock_request, @mock_response)                  
+        end
+        
+        it "should serialize a controller exception when an exception is thrown by find" do
+           setup_find_request
+           @mock_model_class.expects(:find).raises(ArgumentError) 
+           @mock_response.expects(:status=).with(404)
+           @handler.process(@mock_request, @mock_response)        
+        end
+    end
+    
+    describe "when destroying a model instance" do |variable|
+        it "should fail to destroy model if key is not specified" do
+            @mock_request.stubs(:request_method).returns('DELETE')
+            @mock_request.stubs(:path).returns('/foo')
+            @mock_response.expects(:status=).with(404)
+            @handler.process(@mock_request, @mock_response)            
+        end
+        
+        it "should pass HTTP request parameters to model destroy" do
+            setup_destroy_request
+            @mock_request.stubs(:query).returns(:foo => :baz, :bar => :xyzzy)
+            @mock_model_class.expects(:destroy).with do |key, args|
+                key == 'key' and args[:foo] == :baz and args[:bar] == :xyzzy
+            end
+            @handler.service(@mock_request, @mock_response)
+        end
+        
+        it "should generate a 200 response when a model destroy call succeeds" do
+            setup_destroy_request
+            @mock_response.expects(:status=).with(200)
+            @handler.process(@mock_request, @mock_response)      
+        end
+        
+        it "should return a serialized success result when a model destroy call succeeds" do
+            setup_destroy_request
+            @mock_model_class.stubs(:destroy).returns(true)
+            @mock_response.expects(:body=).with("--- true\n")
+            @handler.process(@mock_request, @mock_response)
+        end
+        
+        it "should serialize a controller exception when an exception is thrown by search" do
+            setup_search_request
+            @mock_model_class.expects(:search).raises(ArgumentError) 
+            @mock_response.expects(:status=).with(404)
+            @handler.process(@mock_request, @mock_response)                
+        end
+    end
+    
+    describe "when saving a model instance" do
+        it "should fail to save model if data is not specified" do
+            @mock_request.stubs(:request_method).returns('PUT')
+            @mock_request.stubs(:path).returns('/foo')
+            @mock_request.stubs(:body).returns('')
+            @mock_response.expects(:status=).with(404)
+            @handler.process(@mock_request, @mock_response)            
+        end
+        
+        it "should generate a 200 response when a model save call succeeds" do
+            setup_save_request
+            @mock_response.expects(:status=).with(200)
+            @handler.process(@mock_request, @mock_response)            
+        end
+        
+        it "should return a serialized object when a model save call succeeds" do
+            setup_save_request
+            @mock_model_instance.stubs(:save).returns(@mock_model_instance)
+            @mock_model_instance.expects(:to_yaml).returns('foo')
+            @handler.process(@mock_request, @mock_response)        
+        end
+        
+        it "should serialize a controller exception when an exception is thrown by save" do
+            setup_save_request
+            @mock_model_instance.expects(:save).raises(ArgumentError) 
+            @mock_response.expects(:status=).with(404)
+            @handler.process(@mock_request, @mock_response)                         
+        end
+    end
+    
+    describe "when searching for model instances" do
+        it "should pass HTTP request parameters to model search" do
+            setup_search_request
+            @mock_request.stubs(:query).returns(:foo => :baz, :bar => :xyzzy)
+            @mock_model_class.expects(:search).with do |args|
+                args[:foo] == :baz and args[:bar] == :xyzzy
+            end.returns([])
+            @handler.service(@mock_request, @mock_response)
+        end
+
+        it "should generate a 200 response when a model search call succeeds" do
+            setup_search_request
+            @mock_response.expects(:status=).with(200)
+            @handler.process(@mock_request, @mock_response)      
+        end
+        
+        it "should return a list of serialized objects when a model search call succeeds" do
+            setup_search_request
+            mock_matches = [1..5].collect {|i| mock("model instance #{i}", :to_yaml => "model instance #{i}") }
+            @mock_model_class.stubs(:search).returns(mock_matches)
+            @handler.process(@mock_request, @mock_response)                          
+        end
+        
+        it "should serialize a controller exception when an exception is thrown by destroy" do
+            setup_destroy_request
+            @mock_model_class.expects(:destroy).raises(ArgumentError) 
+            @mock_response.expects(:status=).with(404)
+            @handler.process(@mock_request, @mock_response)                 
+        end       
+    end
+
+    it "should serialize a controller exception if the request fails" do
+        setup_bad_request     
+        @mock_response.expects(:status=).with(404)
+        @handler.process(@mock_request, @mock_response)        
+    end
+end
diff --git a/examples/etc/otherfile b/spec/unit/network/http/webrick/xmlrpc.rb
similarity index 100%
copy from examples/etc/otherfile
copy to spec/unit/network/http/webrick/xmlrpc.rb
diff --git a/spec/unit/network/http_pool.rb b/spec/unit/network/http_pool.rb
new file mode 100755
index 0000000..1fbc174
--- /dev/null
+++ b/spec/unit/network/http_pool.rb
@@ -0,0 +1,240 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-11-26.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/network/http_pool'
+
+describe Puppet::Network::HttpPool, " when adding certificate information to http instances" do
+    before do
+        @http = mock 'http'
+        [:cert_store=, :verify_mode=, :ca_file=, :cert=, :key=].each { |m| @http.stubs(m) }
+        @store = stub 'store'
+        [:add_file,:purpose=].each { |m| @store.stubs(m) }
+    end
+
+    it "should have keep-alive disabled" do
+        Puppet::Network::HttpPool::HTTP_KEEP_ALIVE.should be_false
+    end
+
+    it "should do nothing if no certificate is available" do
+        Puppet::Network::HttpPool.expects(:read_cert).returns(false)
+        @http.expects(:cert=).never
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should add a certificate store" do
+        Puppet::Network::HttpPool.stubs(:read_cert).returns(true)
+        Puppet::Network::HttpPool.stubs(:key).returns(:mykey)
+        OpenSSL::X509::Store.expects(:new).returns(@store)
+        @http.expects(:cert_store=).with(@store)
+
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should add the local CA cert to the certificate store" do
+        Puppet::Network::HttpPool.stubs(:read_cert).returns(true)
+        OpenSSL::X509::Store.expects(:new).returns(@store)
+        Puppet.settings.stubs(:value).with(:localcacert).returns("/some/file")
+        Puppet.settings.stubs(:value).with(:localcacert).returns("/some/file")
+        @store.expects(:add_file).with("/some/file")
+
+        Puppet::Network::HttpPool.stubs(:key).returns(:whatever)
+
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should set the purpose of the cert store to OpenSSL::X509::PURPOSE_SSL_CLIENT" do
+        Puppet::Network::HttpPool.stubs(:read_cert).returns(true)
+        Puppet::Network::HttpPool.stubs(:key).returns(:mykey)
+        OpenSSL::X509::Store.expects(:new).returns(@store)
+
+        @store.expects(:purpose=).with(OpenSSL::X509::PURPOSE_SSL_CLIENT)
+
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should add the client certificate" do
+        Puppet::Network::HttpPool.stubs(:read_cert).returns(true)
+        Puppet::Network::HttpPool.stubs(:cert).returns(:mycert)
+        Puppet::Network::HttpPool.stubs(:key).returns(:mykey)
+        OpenSSL::X509::Store.expects(:new).returns(@store)
+
+        @http.expects(:cert=).with(:mycert)
+
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should add the client key" do
+        Puppet::Network::HttpPool.stubs(:read_cert).returns(true)
+        Puppet::Network::HttpPool.stubs(:key).returns(:mykey)
+        OpenSSL::X509::Store.expects(:new).returns(@store)
+
+        @http.expects(:key=).with(:mykey)
+
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should set the verify mode to OpenSSL::SSL::VERIFY_PEER" do
+        Puppet::Network::HttpPool.stubs(:read_cert).returns(true)
+        Puppet::Network::HttpPool.stubs(:key).returns(:mykey)
+        OpenSSL::X509::Store.expects(:new).returns(@store)
+
+        @http.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
+
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should set the ca file" do
+        Puppet::Network::HttpPool.stubs(:read_cert).returns(true)
+        Puppet.settings.stubs(:value).with(:localcacert).returns("/some/file")
+        OpenSSL::X509::Store.expects(:new).returns(@store)
+
+        @http.expects(:ca_file=).with("/some/file")
+
+        Puppet::Network::HttpPool.stubs(:key).returns(:whatever)
+
+        Puppet::Network::HttpPool.cert_setup(@http)
+    end
+
+    it "should set up certificate information when creating http instances" do
+        Puppet::Network::HttpPool.expects(:cert_setup).with { |i| i.is_a?(Net::HTTP) }
+        Puppet::Network::HttpPool.http_instance("one", "two")
+    end
+
+    after do
+        Puppet::Network::HttpPool.clear_http_instances
+    end
+
+    describe "when managing http instances" do
+        def stub_settings(settings)
+            settings.each do |param, value|
+                Puppet.settings.stubs(:value).with(param).returns(value)
+            end
+        end
+
+        before do
+            # All of hte cert stuff is tested elsewhere
+            Puppet::Network::HttpPool.stubs(:cert_setup)
+        end
+
+        it "should return an http instance created with the passed host and port" do
+            http = stub 'http', :use_ssl= => nil, :read_timeout= => nil, :open_timeout= => nil, :enable_post_connection_check= => nil, :started? => false
+            Net::HTTP.expects(:new).with("me", 54321, nil, nil).returns(http)
+            Puppet::Network::HttpPool.http_instance("me", 54321).should equal(http)
+        end
+
+        it "should enable ssl on the http instance" do
+            Puppet::Network::HttpPool.http_instance("me", 54321).instance_variable_get("@use_ssl").should be_true
+        end
+
+        it "should set the read timeout" do
+            Puppet::Network::HttpPool.http_instance("me", 54321).read_timeout.should == 120
+        end
+
+        it "should set the open timeout" do
+            Puppet::Network::HttpPool.http_instance("me", 54321).open_timeout.should == 120
+        end
+
+        it "should default to http_enable_post_connection_check being enabled" do
+            Puppet.settings[:http_enable_post_connection_check].should be_true
+        end
+
+        # JJM: I'm not sure if this is correct, as this really follows the
+        # configuration option.
+        it "should set enable_post_connection_check true " do
+            Puppet::Network::HttpPool.http_instance("me", 54321).instance_variable_get("@enable_post_connection_check").should be_true
+        end
+
+        it "should create the http instance with the proxy host and port set if the http_proxy is not set to 'none'" do
+            stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+            Puppet::Network::HttpPool.http_instance("me", 54321).open_timeout.should == 120
+        end
+
+        describe "when http keep-alive is enabled" do
+            before do
+                Puppet::Network::HttpPool.stubs(:keep_alive?).returns true
+            end
+
+            it "should cache http instances" do
+                stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+                old = Puppet::Network::HttpPool.http_instance("me", 54321)
+                Puppet::Network::HttpPool.http_instance("me", 54321).should equal(old)
+            end
+
+            it "should have a mechanism for getting a new http instance instead of the cached instance" do
+                stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+                old = Puppet::Network::HttpPool.http_instance("me", 54321)
+                Puppet::Network::HttpPool.http_instance("me", 54321, true).should_not equal(old)
+            end
+
+            it "should close existing, open connections when requesting a new connection" do
+                stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+                old = Puppet::Network::HttpPool.http_instance("me", 54321)
+                old.expects(:started?).returns(true)
+                old.expects(:finish)
+                Puppet::Network::HttpPool.http_instance("me", 54321, true)
+            end
+
+            it "should have a mechanism for clearing the http cache" do
+                stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+                old = Puppet::Network::HttpPool.http_instance("me", 54321)
+                Puppet::Network::HttpPool.http_instance("me", 54321).should equal(old)
+                old = Puppet::Network::HttpPool.http_instance("me", 54321)
+                Puppet::Network::HttpPool.clear_http_instances
+                Puppet::Network::HttpPool.http_instance("me", 54321).should_not equal(old)
+            end
+
+            it "should close open http connections when clearing the cache" do
+                stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+                one = Puppet::Network::HttpPool.http_instance("me", 54321)
+                one.expects(:started?).returns(true)
+                one.expects(:finish).returns(true)
+                Puppet::Network::HttpPool.clear_http_instances
+            end
+
+            it "should not close unopened http connections when clearing the cache" do
+                stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+                one = Puppet::Network::HttpPool.http_instance("me", 54321)
+                one.expects(:started?).returns(false)
+                one.expects(:finish).never
+                Puppet::Network::HttpPool.clear_http_instances
+            end
+        end
+
+        describe "when http keep-alive is disabled" do
+            before do
+                Puppet::Network::HttpPool.stubs(:keep_alive?).returns false
+            end
+
+            it "should not cache http instances" do
+                stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :http_enable_post_connection_check => true
+                old = Puppet::Network::HttpPool.http_instance("me", 54321)
+                Puppet::Network::HttpPool.http_instance("me", 54321).should_not equal(old)
+            end
+        end
+
+        # We mostly have to do this for testing, since in real life people
+        # won't change certs within a single process.
+        it "should remove its loaded certificate when clearing the cache" do
+            Puppet::Network::HttpPool.instance_variable_set("@cert", :yay)
+            Puppet::Network::HttpPool.clear_http_instances
+            # Can't use the accessor, because it will read the cert in
+            Puppet::Network::HttpPool.instance_variable_get("@cert").should be_nil
+        end
+
+        # We mostly have to do this for testing, since in real life people
+        # won't change certs within a single process.
+        it "should remove its loaded key when clearing the cache" do
+            Puppet::Network::HttpPool.instance_variable_set("@key", :yay)
+            Puppet::Network::HttpPool.clear_http_instances
+            # Can't use the accessor, because it will read the cert in
+            Puppet::Network::HttpPool.instance_variable_get("@key").should be_nil
+        end
+
+        after do
+            Puppet::Network::HttpPool.clear_http_instances
+        end
+    end
+end
diff --git a/spec/unit/network/server.rb b/spec/unit/network/server.rb
new file mode 100644
index 0000000..4e47c22
--- /dev/null
+++ b/spec/unit/network/server.rb
@@ -0,0 +1,316 @@
+#!/usr/bin/env ruby
+#
+#  Created by Rick Bradley on 2007-10-03.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/network/server'
+
+describe Puppet::Network::Server, "when initializing" do
+    before do
+        @mock_http_server_class = mock('http server class')
+        Puppet.stubs(:[]).with(:servertype).returns(:suparserver)
+        Puppet::Network::HTTP.stubs(:server_class_by_type).returns(@mock_http_server_class)
+    end
+    
+    it "should allow specifying a listening address" do
+        Puppet.stubs(:[]).with(:masterport).returns('')
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1")
+        @server.address.should == "127.0.0.1"
+    end
+
+    it "should allow specifying a listening port" do
+        Puppet.stubs(:[]).with(:bindaddress).returns('')
+        @server = Puppet::Network::Server.new(:port => 31337)
+        @server.port.should == 31337
+    end
+    
+    it "should use the Puppet configurator to find a default listening address" do
+        Puppet.stubs(:[]).with(:masterport).returns('')
+        Puppet.expects(:[]).with(:bindaddress).returns("10.0.0.1")
+        @server = Puppet::Network::Server.new
+        @server.address.should == "10.0.0.1"
+    end
+
+    it "should use the Puppet configurator to find a default listening port" do
+        Puppet.stubs(:[]).with(:bindaddress).returns('')
+        Puppet.expects(:[]).with(:masterport).returns(6667)
+        @server = Puppet::Network::Server.new
+        @server.port.should == 6667
+    end
+
+    it "should fail to initialize if no listening address can be found" do
+        Puppet.stubs(:[]).with(:masterport).returns(6667)
+        Puppet.stubs(:[]).with(:bindaddress).returns(nil)
+        Proc.new { Puppet::Network::Server.new }.should raise_error(ArgumentError)
+    end
+    
+    it "should fail to initialize if no listening port can be found" do
+        Puppet.stubs(:[]).with(:bindaddress).returns("127.0.0.1")
+        Puppet.stubs(:[]).with(:masterport).returns(nil)
+        Proc.new { Puppet::Network::Server.new }.should raise_error(ArgumentError)        
+    end
+
+    it "should use the Puppet configurator to determine which HTTP server will be used to provide access to clients" do
+        Puppet.expects(:[]).with(:servertype).returns(:suparserver)
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+        @server.server_type.should == :suparserver
+    end
+  
+    it "should fail to initialize if there is no HTTP server known to the Puppet configurator" do
+        Puppet.expects(:[]).with(:servertype).returns(nil)
+        Proc.new { Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337) }.should raise_error
+    end
+ 
+    it "should ask the Puppet::Network::HTTP class to fetch the proper HTTP server class" do
+        Puppet::Network::HTTP.expects(:server_class_by_type).with(:suparserver).returns(@mock_http_server_class)
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+    end
+    
+    it "should fail if the HTTP server class is unknown" do
+        Puppet::Network::HTTP.stubs(:server_class_by_type).returns(nil)
+        Proc.new { Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337) }.should raise_error(ArgumentError)
+    end
+  
+    it "should allow registering indirections" do
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337, :handlers => [ :foo, :bar, :baz])
+        Proc.new { @server.unregister(:foo, :bar, :baz) }.should_not raise_error
+    end
+  
+    it "should not be listening after initialization" do
+        Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337).should_not be_listening
+    end
+end
+
+describe Puppet::Network::Server, "in general" do
+    before do
+        @mock_http_server_class = mock('http server class')
+        Puppet::Network::HTTP.stubs(:server_class_by_type).returns(@mock_http_server_class)
+        Puppet.stubs(:[]).with(:servertype).returns(:suparserver)
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+    end
+  
+    it "should allow registering an indirection for client access by specifying its indirection name" do
+        Proc.new { @server.register(:foo) }.should_not raise_error
+    end
+  
+    it "should require at least one indirection name when registering indirections for client access" do
+        Proc.new { @server.register }.should raise_error(ArgumentError)
+    end
+  
+    it "should allow for numerous indirections to be registered at once for client access" do
+        Proc.new { @server.register(:foo, :bar, :baz) }.should_not raise_error
+    end
+
+    it "should allow the use of indirection names to specify which indirections are to be no longer accessible to clients" do
+        @server.register(:foo)
+        Proc.new { @server.unregister(:foo) }.should_not raise_error    
+    end
+
+    it "should leave other indirections accessible to clients when turning off indirections" do
+        @server.register(:foo, :bar)
+        @server.unregister(:foo)
+        Proc.new { @server.unregister(:bar)}.should_not raise_error
+    end
+  
+    it "should allow specifying numerous indirections which are to be no longer accessible to clients" do
+        @server.register(:foo, :bar)
+        Proc.new { @server.unregister(:foo, :bar) }.should_not raise_error
+    end
+    
+    it "should not turn off any indirections if given unknown indirection names to turn off" do
+        @server.register(:foo, :bar)
+        Proc.new { @server.unregister(:foo, :bar, :baz) }.should raise_error(ArgumentError)
+        Proc.new { @server.unregister(:foo, :bar) }.should_not raise_error
+    end
+  
+    it "should not allow turning off unknown indirection names" do
+        @server.register(:foo, :bar)
+        Proc.new { @server.unregister(:baz) }.should raise_error(ArgumentError)
+    end
+  
+    it "should disable client access immediately when turning off indirections" do
+        @server.register(:foo, :bar)
+        @server.unregister(:foo)    
+        Proc.new { @server.unregister(:foo) }.should raise_error(ArgumentError)
+    end
+  
+    it "should allow turning off all indirections at once" do
+        @server.register(:foo, :bar)
+        @server.unregister
+        [ :foo, :bar, :baz].each do |indirection|
+            Proc.new { @server.unregister(indirection) }.should raise_error(ArgumentError)
+        end
+    end
+  
+    it "should provide a means of determining whether it is listening" do
+        @server.should respond_to(:listening?)
+    end
+  
+    it "should provide a means of determining which HTTP server will be used to provide access to clients" do
+        @server.server_type.should == :suparserver
+    end
+    
+    it "should allow for multiple configurations, each handling different indirections" do
+        @server2 = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+        @server.register(:foo, :bar)
+        @server2.register(:foo, :xyzzy)
+        @server.unregister(:foo, :bar)
+        @server2.unregister(:foo, :xyzzy)
+        Proc.new { @server.unregister(:xyzzy) }.should raise_error(ArgumentError)
+        Proc.new { @server2.unregister(:bar) }.should raise_error(ArgumentError)
+    end  
+
+    it "should provide a means of determining which protocols are in use" do
+        @server.should respond_to(:protocols)
+    end
+    
+    it "should only support the REST protocol at this time" do
+        @server.protocols.should == [ :rest ]
+    end
+    
+    it "should provide a means of determining the listening address" do
+        @server.address.should == "127.0.0.1"
+    end
+    
+    it "should provide a means of determining the listening port" do
+        @server.port.should == 31337
+    end
+end
+
+describe Puppet::Network::Server, "when listening is off" do
+    before do
+        @mock_http_server_class = mock('http server class')
+        Puppet::Network::HTTP.stubs(:server_class_by_type).returns(@mock_http_server_class)
+        Puppet.stubs(:[]).with(:servertype).returns(:suparserver)
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+        @mock_http_server = mock('http server')
+        @mock_http_server.stubs(:listen)
+        @server.stubs(:http_server).returns(@mock_http_server)
+    end
+
+    it "should indicate that it is not listening" do
+        @server.should_not be_listening
+    end  
+  
+    it "should not allow listening to be turned off" do
+        Proc.new { @server.unlisten }.should raise_error(RuntimeError)
+    end
+  
+    it "should allow listening to be turned on" do
+        Proc.new { @server.listen }.should_not raise_error
+    end
+    
+end
+
+describe Puppet::Network::Server, "when listening is on" do
+    before do
+        @mock_http_server_class = mock('http server class')
+        Puppet::Network::HTTP.stubs(:server_class_by_type).returns(@mock_http_server_class)
+        Puppet.stubs(:[]).with(:servertype).returns(:suparserver)
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+        @mock_http_server = mock('http server')
+        @mock_http_server.stubs(:listen)
+        @mock_http_server.stubs(:unlisten)
+        @server.stubs(:http_server).returns(@mock_http_server)
+        @server.listen
+    end
+  
+    it "should indicate that listening is turned off" do
+        @server.should be_listening
+    end
+    
+    it "should not allow listening to be turned on" do
+        Proc.new { @server.listen }.should raise_error(RuntimeError)
+    end
+  
+    it "should allow listening to be turned off" do
+        Proc.new { @server.unlisten }.should_not raise_error
+    end
+end
+ 
+describe Puppet::Network::Server, "when listening is being turned on" do
+    before do
+        @mock_http_server_class = mock('http server class')
+        Puppet::Network::HTTP.stubs(:server_class_by_type).returns(@mock_http_server_class)
+        Puppet.stubs(:[]).with(:servertype).returns(:suparserver)
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337, :handlers => [:node])
+        @mock_http_server = mock('http server')
+        @mock_http_server.stubs(:listen)
+    end
+
+    it "should fetch an instance of an HTTP server" do
+        @server.stubs(:http_server_class).returns(@mock_http_server_class)
+        @mock_http_server_class.expects(:new).returns(@mock_http_server)
+        @server.listen        
+    end
+
+    it "should cause the HTTP server to listen" do
+        @server.stubs(:http_server).returns(@mock_http_server)
+        @mock_http_server.expects(:listen)
+        @server.listen
+    end
+    
+    it "should pass the listening address to the HTTP server" do
+       @server.stubs(:http_server).returns(@mock_http_server)
+       @mock_http_server.expects(:listen).with do |args|
+            args[:address] == '127.0.0.1'
+       end
+       @server.listen
+    end
+    
+    it "should pass the listening port to the HTTP server" do
+      @server.stubs(:http_server).returns(@mock_http_server)
+      @mock_http_server.expects(:listen).with do |args|
+           args[:port] == 31337
+      end
+      @server.listen
+    end
+    
+    it "should pass a list of handlers to the HTTP server" do
+      @server.stubs(:http_server).returns(@mock_http_server)
+      @mock_http_server.expects(:listen).with do |args|
+           args[:handlers] == [ :node ]
+      end
+      @server.listen
+    end
+    
+    it "should pass a list of protocols to the HTTP server" do
+      @server.stubs(:http_server).returns(@mock_http_server)
+      @mock_http_server.expects(:listen).with do |args|
+           args[:protocols] == [ :rest ]
+      end
+      @server.listen      
+    end
+end
+
+describe Puppet::Network::Server, "when listening is being turned off" do
+    before do
+        @mock_http_server_class = mock('http server class')
+        Puppet::Network::HTTP.stubs(:server_class_by_type).returns(@mock_http_server_class)
+        Puppet.stubs(:[]).with(:servertype).returns(:suparserver)
+        @server = Puppet::Network::Server.new(:address => "127.0.0.1", :port => 31337)
+        @mock_http_server = mock('http server')
+        @mock_http_server.stubs(:listen)
+        @server.stubs(:http_server).returns(@mock_http_server)
+        @server.listen
+    end
+
+    it "should cause the HTTP server to stop listening when listening is turned off" do
+        @mock_http_server.expects(:unlisten)
+        @server.unlisten
+    end
+
+    it "should not allow for indirections to be turned off" do
+        @server.register(:foo)
+        Proc.new { @server.unregister(:foo) }.should raise_error(RuntimeError) 
+    end
+end
+
+                
+describe Class.new, "put these somewhere" do
+    it "should have the ability to use a class-level from_ hook (from_yaml, from_text, etc.) that can be called, based on content-type header, to allow for different deserializations of an object" 
+    it "should allow from_* on the inbound :data packet (look at its content_type) when doing a PUT/.new.save"
+    it "should prepend a rest version number on the path (w00t)"
+    it "should ... on server side, .save should from_yaml, then foo.save(args) instead of just Foo.new.save(args)"
+end
diff --git a/spec/unit/node.rb b/spec/unit/node.rb
new file mode 100755
index 0000000..421fcd6
--- /dev/null
+++ b/spec/unit/node.rb
@@ -0,0 +1,210 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe Puppet::Node, " when initializing" do
+    before do
+        @node = Puppet::Node.new("testnode")
+    end
+
+    it "should set the node name" do
+        @node.name.should == "testnode"
+    end
+
+    it "should not allow nil node names" do
+        proc { Puppet::Node.new(nil) }.should raise_error(ArgumentError)
+    end
+
+    it "should default to an empty parameter hash" do
+        @node.parameters.should == {}
+    end
+
+    it "should default to an empty class array" do
+        @node.classes.should == []
+    end
+
+    it "should note its creation time" do
+        @node.time.should be_instance_of(Time)
+    end
+
+    it "should accept parameters passed in during initialization" do
+        params = {"a" => "b"}
+        @node = Puppet::Node.new("testing", :parameters => params)
+        @node.parameters.should == params
+    end
+
+    it "should accept classes passed in during initialization" do
+        classes = %w{one two}
+        @node = Puppet::Node.new("testing", :classes => classes)
+        @node.classes.should == classes
+    end
+
+    it "should always return classes as an array" do
+        @node = Puppet::Node.new("testing", :classes => "myclass")
+        @node.classes.should == ["myclass"]
+    end
+
+    it "should accept an environment value" do
+        Puppet.settings.stubs(:value).with(:environments).returns("myenv")
+        @node = Puppet::Node.new("testing", :environment => "myenv")
+        @node.environment.should == "myenv"
+    end
+
+    it "should validate the environment" do
+        Puppet.settings.stubs(:value).with(:environments).returns("myenv")
+        proc { Puppet::Node.new("testing", :environment => "other") }.should raise_error(ArgumentError)
+    end
+
+    it "should accept names passed in" do
+        @node = Puppet::Node.new("testing", :names => ["myenv"])
+        @node.names.should == ["myenv"]
+    end
+end
+
+describe Puppet::Node, " when returning the environment" do
+    before do
+        Puppet.settings.stubs(:value).with(:environments).returns("one,two")
+        Puppet.settings.stubs(:value).with(:environment).returns("one")
+        @node = Puppet::Node.new("testnode")
+    end
+
+    it "should return the 'environment' fact if present and there is no explicit environment" do
+        @node.parameters = {"environment" => "two"}
+        @node.environment.should == "two"
+    end
+
+    it "should use the default environment if there is no environment fact nor explicit environment" do
+        env = mock 'environment', :name => :myenv
+        Puppet::Node::Environment.expects(:new).returns(env)
+        @node.environment.should == "myenv"
+    end
+
+    it "should fail if the parameter environment is invalid" do
+        @node.parameters = {"environment" => "three"}
+        proc { @node.environment }.should raise_error(ArgumentError)
+    end
+
+    it "should fail if the parameter environment is invalid" do
+        @node.parameters = {"environment" => "three"}
+        proc { @node.environment }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Node, " when merging facts" do
+    before do
+        @node = Puppet::Node.new("testnode")
+        Puppet::Node::Facts.stubs(:find).with(@node.name).returns(Puppet::Node::Facts.new(@node.name, "one" => "c", "two" => "b"))
+    end
+
+    it "should prefer parameters already set on the node over facts from the node" do
+        @node.parameters = {"one" => "a"}
+        @node.fact_merge
+        @node.parameters["one"].should == "a"
+    end
+
+    it "should add passed parameters to the parameter list" do
+        @node.parameters = {"one" => "a"}
+        @node.fact_merge
+        @node.parameters["two"].should == "b"
+    end
+
+    it "should accept arbitrary parameters to merge into its parameters" do
+        @node.parameters = {"one" => "a"}
+        @node.merge "two" => "three"
+        @node.parameters["two"].should == "three"
+    end
+end
+
+describe Puppet::Node, " when indirecting" do
+    it "should redirect to the indirection" do
+        @indirection = stub 'indirection', :name => :node
+        Puppet::Node.stubs(:indirection).returns(@indirection)
+        @indirection.expects(:find)
+        Puppet::Node.find(:my_node.to_s)
+    end
+
+    it "should default to the 'plain' node terminus" do
+        Puppet::Node.indirection.terminus_class.should == :plain
+    end
+
+    it "should not have a cache class defined" do
+        Puppet::Node.indirection.cache_class.should be_nil
+    end
+
+    after do
+        Puppet::Indirector::Indirection.clear_cache
+    end
+end
+
+describe Puppet::Node do
+    # LAK:NOTE This is used to keep track of when a given node has connected,
+    # so we can report on nodes that do not appear to connecting to the
+    # central server.
+    it "should provide a method for noting that the node has connected"
+end
+
+describe Puppet::Node, " when searching for nodes" do
+    before do
+        @searcher = Puppet::Node
+        @facts = Puppet::Node::Facts.new("foo", "hostname" => "yay", "domain" => "domain.com")
+        @node = Puppet::Node.new("foo")
+        Puppet::Node::Facts.stubs(:find).with("foo").returns(@facts)
+    end
+
+    it "should return the first node found using the generated list of names" do
+        @searcher.expects(:find).with("foo").returns(nil)
+        @searcher.expects(:find).with("yay.domain.com").returns(@node)
+        @searcher.find_by_any_name("foo").should equal(@node)
+    end
+
+    it "should search for the node by its key first" do
+        names = []
+        @searcher.expects(:find).with do |name|
+            names << name
+            names == %w{foo}
+        end.returns(@node)
+        @searcher.find_by_any_name("foo").should equal(@node)
+    end
+
+    it "should search for the rest of the names inversely by length" do
+        names = []
+        @facts.values["fqdn"] = "longer.than.the.normal.fqdn.com"
+        @searcher.stubs(:find).with do |name|
+            names << name
+        end
+        @searcher.find_by_any_name("foo")
+        # Strip off the key
+        names.shift
+
+        # And the 'default'
+        names.pop
+
+        length = 100
+        names.each do |name|
+            (name.length < length).should be_true
+            length = name.length
+        end
+    end
+
+    it "should attempt to find a default node if no names are found" do
+        names = []
+        @searcher.stubs(:find).with do |name|
+            names << name
+        end.returns(nil)
+        @searcher.find_by_any_name("foo")
+        names[-1].should == "default"
+    end
+
+    it "should flush the node cache using the :filetimeout parameter" do
+        node2 = Puppet::Node.new("foo2")
+        Puppet[:filetimeout] = -1
+        # I couldn't get this to work with :expects
+        @searcher.stubs(:find).returns(@node, node2).then.raises(ArgumentError)
+        @searcher.find_by_any_name("foo").should equal(@node)
+        @searcher.find_by_any_name("foo").should equal(node2)
+    end
+
+    after do
+        Puppet.settings.clear
+    end
+end
diff --git a/spec/unit/node/catalog.rb b/spec/unit/node/catalog.rb
new file mode 100755
index 0000000..cd27b92
--- /dev/null
+++ b/spec/unit/node/catalog.rb
@@ -0,0 +1,833 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Node::Catalog, " when compiling" do
+    it "should accept tags" do
+        config = Puppet::Node::Catalog.new("mynode")
+        config.tag("one")
+        config.tags.should == %w{one}
+    end
+
+    it "should accept multiple tags at once" do
+        config = Puppet::Node::Catalog.new("mynode")
+        config.tag("one", "two")
+        config.tags.should == %w{one two}
+    end
+
+    it "should convert all tags to strings" do
+        config = Puppet::Node::Catalog.new("mynode")
+        config.tag("one", :two)
+        config.tags.should == %w{one two}
+    end
+
+    it "should tag with both the qualified name and the split name" do
+        config = Puppet::Node::Catalog.new("mynode")
+        config.tag("one::two")
+        config.tags.include?("one").should be_true
+        config.tags.include?("one::two").should be_true
+    end
+
+    it "should accept classes" do
+        config = Puppet::Node::Catalog.new("mynode")
+        config.add_class("one")
+        config.classes.should == %w{one}
+        config.add_class("two", "three")
+        config.classes.should == %w{one two three}
+    end
+
+    it "should tag itself with passed class names" do
+        config = Puppet::Node::Catalog.new("mynode")
+        config.add_class("one")
+        config.tags.should == %w{one}
+    end
+end
+
+describe Puppet::Node::Catalog, " when extracting" do
+    it "should return extraction result as the method result" do
+        config = Puppet::Node::Catalog.new("mynode")
+        config.expects(:extraction_format).returns(:whatever)
+        config.expects(:extract_to_whatever).returns(:result)
+        config.extract.should == :result
+    end
+end
+
+describe Puppet::Node::Catalog, " when extracting transobjects" do
+
+    def mkscope
+        @parser = Puppet::Parser::Parser.new :Code => ""
+        @node = Puppet::Node.new("mynode")
+        @compiler = Puppet::Parser::Compiler.new(@node, @parser)
+
+        # XXX This is ridiculous.
+        @compiler.send(:evaluate_main)
+        @scope = @compiler.topscope
+    end
+
+    def mkresource(type, name)
+        Puppet::Parser::Resource.new(:type => type, :title => name, :source => @source, :scope => @scope)
+    end
+
+    it "should always create a TransBucket for the 'main' class" do
+        config = Puppet::Node::Catalog.new("mynode")
+
+        @scope = mkscope
+        @source = mock 'source'
+
+        main = mkresource("class", :main)
+        config.add_vertex(main)
+
+        bucket = mock 'bucket'
+        bucket.expects(:classes=).with(config.classes)
+        main.stubs(:builtin?).returns(false)
+        main.expects(:to_transbucket).returns(bucket)
+
+        config.extract_to_transportable.should equal(bucket)
+    end
+
+    # This isn't really a spec-style test, but I don't know how better to do it.
+    it "should transform the resource graph into a tree of TransBuckets and TransObjects" do
+        config = Puppet::Node::Catalog.new("mynode")
+
+        @scope = mkscope
+        @source = mock 'source'
+
+        defined = mkresource("class", :main)
+        builtin = mkresource("file", "/yay")
+
+        config.add_edge(defined, builtin)
+
+        bucket = []
+        bucket.expects(:classes=).with(config.classes)
+        defined.stubs(:builtin?).returns(false)
+        defined.expects(:to_transbucket).returns(bucket)
+        builtin.expects(:to_transobject).returns(:builtin)
+
+        config.extract_to_transportable.should == [:builtin]
+    end
+
+    # Now try it with a more complicated graph -- a three tier graph, each tier
+    it "should transform arbitrarily deep graphs into isomorphic trees" do
+        config = Puppet::Node::Catalog.new("mynode")
+
+        @scope = mkscope
+        @scope.stubs(:tags).returns([])
+        @source = mock 'source'
+
+        # Create our scopes.
+        top = mkresource "class", :main
+        topbucket = []
+        topbucket.expects(:classes=).with([])
+        top.expects(:to_trans).returns(topbucket)
+        topres = mkresource "file", "/top"
+        topres.expects(:to_trans).returns(:topres)
+        config.add_edge top, topres
+
+        middle = mkresource "class", "middle"
+        middle.expects(:to_trans).returns([])
+        config.add_edge top, middle
+        midres = mkresource "file", "/mid"
+        midres.expects(:to_trans).returns(:midres)
+        config.add_edge middle, midres
+
+        bottom = mkresource "class", "bottom"
+        bottom.expects(:to_trans).returns([])
+        config.add_edge middle, bottom
+        botres = mkresource "file", "/bot"
+        botres.expects(:to_trans).returns(:botres)
+        config.add_edge bottom, botres
+
+        toparray = config.extract_to_transportable
+
+        # This is annoying; it should look like:
+        #   [[[:botres], :midres], :topres]
+        # but we can't guarantee sort order.
+        toparray.include?(:topres).should be_true
+
+        midarray = toparray.find { |t| t.is_a?(Array) }
+        midarray.include?(:midres).should be_true
+        botarray = midarray.find { |t| t.is_a?(Array) }
+        botarray.include?(:botres).should be_true
+    end
+end
+
+describe Puppet::Node::Catalog, " when converting to a transobject catalog" do
+    class TestResource
+        attr_accessor :name, :virtual, :builtin
+        def initialize(name, options = {})
+            @name = name
+            options.each { |p,v| send(p.to_s + "=", v) }
+        end
+
+        def ref
+            if builtin?
+                "File[%s]" % name
+            else
+                "Class[%s]" % name
+            end
+        end
+
+        def virtual?
+            virtual
+        end
+
+        def builtin?
+            builtin
+        end
+
+        def to_transobject
+            Puppet::TransObject.new(name, builtin? ? "file" : "class")
+        end
+    end
+
+    before do
+        @original = Puppet::Node::Catalog.new("mynode")
+        @original.tag(*%w{one two three})
+        @original.add_class *%w{four five six}
+
+        @top            = TestResource.new 'top'
+        @topobject      = TestResource.new 'topobject', :builtin => true
+        @virtual        = TestResource.new 'virtual', :virtual => true
+        @virtualobject  = TestResource.new 'virtualobject', :builtin => true, :virtual => true
+        @middle         = TestResource.new 'middle'
+        @middleobject   = TestResource.new 'middleobject', :builtin => true
+        @bottom         = TestResource.new 'bottom'
+        @bottomobject   = TestResource.new 'bottomobject', :builtin => true
+
+        @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)
+
+        @catalog = @original.to_transportable
+    end
+
+    it "should add all resources as TransObjects" do
+        @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::TransObject) }
+    end
+
+    it "should not extract defined virtual resources" do
+        @catalog.vertices.find { |v| v.name == "virtual" }.should be_nil
+    end
+
+    it "should not extract builtin virtual resources" do
+        @catalog.vertices.find { |v| v.name == "virtualobject" }.should be_nil
+    end
+
+    it "should copy the tag list to the new catalog" do
+        @catalog.tags.sort.should == @original.tags.sort
+    end
+
+    it "should copy the class list to the new catalog" do
+        @catalog.classes.should == @original.classes
+    end
+
+    it "should duplicate the original edges" do
+        @original.edges.each do |edge|
+            next if edge.source.virtual? or edge.target.virtual?
+            source = @catalog.resource(edge.source.ref)
+            target = @catalog.resource(edge.target.ref)
+
+            source.should_not be_nil
+            target.should_not be_nil
+            @catalog.edge?(source, target).should be_true
+        end
+    end
+
+    it "should set itself as the catalog for each converted resource" do
+        @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) }
+    end
+end
+
+describe Puppet::Node::Catalog, " when converting to a RAL catalog" do
+    before do
+        @original = Puppet::Node::Catalog.new("mynode")
+        @original.tag(*%w{one two three})
+        @original.add_class *%w{four five six}
+
+        @top            = Puppet::TransObject.new 'top', "class"
+        @topobject      = Puppet::TransObject.new '/topobject', "file"
+        @middle         = Puppet::TransObject.new 'middle', "class"
+        @middleobject   = Puppet::TransObject.new '/middleobject', "file"
+        @bottom         = Puppet::TransObject.new 'bottom', "class"
+        @bottomobject   = Puppet::TransObject.new '/bottomobject', "file"
+
+        @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject]
+
+        @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)
+
+        @catalog = @original.to_ral
+    end
+
+    it "should add all resources as RAL instances" do
+        @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::Type) }
+    end
+
+    it "should copy the tag list to the new catalog" do
+        @catalog.tags.sort.should == @original.tags.sort
+    end
+
+    it "should copy the class list to the new catalog" do
+        @catalog.classes.should == @original.classes
+    end
+
+    it "should duplicate the original edges" do
+        @original.edges.each do |edge|
+            @catalog.edge?(@catalog.resource(edge.source.ref), @catalog.resource(edge.target.ref)).should be_true
+        end
+    end
+
+    it "should set itself as the catalog for each converted resource" do
+        @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) }
+    end
+
+    # This tests #931.
+    it "should not lose track of resources whose names vary" do
+        changer = Puppet::TransObject.new 'changer', 'test'
+
+        config = Puppet::Node::Catalog.new('test')
+        config.add_resource(changer)
+        config.add_resource(@top)
+
+        config.add_edge(@top, changer)
+
+        resource = stub 'resource', :name => "changer2", :title => "changer2", :ref => "Test[changer2]", :catalog= => nil, :remove => nil
+
+        #changer is going to get duplicated as part of a fix for aliases 1094
+        changer.expects(:dup).returns(changer)
+        changer.expects(:to_type).returns(resource)
+
+        newconfig = nil
+
+        Puppet::Type.allclear
+
+        proc { @catalog = config.to_ral }.should_not raise_error
+        @catalog.resource("Test[changer2]").should equal(resource)
+    end
+
+    after do
+        # Remove all resource instances.
+        @catalog.clear(true)
+    end
+end
+
+describe Puppet::Node::Catalog, " when functioning as a resource container" do
+    before do
+        @catalog = Puppet::Node::Catalog.new("host")
+        @one = stub 'resource1', :ref => "Me[one]", :catalog= => nil
+        @two = stub 'resource2', :ref => "Me[two]", :catalog= => nil
+        @dupe = stub 'resource3', :ref => "Me[one]", :catalog= => nil
+    end
+
+    it "should provide a method to add one or more resources" do
+        @catalog.add_resource @one, @two
+        @catalog.resource(@one.ref).should equal(@one)
+        @catalog.resource(@two.ref).should equal(@two)
+    end
+
+    it "should set itself as the resource's catalog if it is not a relationship graph" do
+        @one.expects(:catalog=).with(@catalog)
+        @catalog.add_resource @one
+    end
+
+    it "should not set itself as the resource's catalog if it is a relationship graph" do
+        @one.expects(:catalog=).never
+        @catalog.is_relationship_graph = true
+        @catalog.add_resource @one
+    end
+
+    it "should make all vertices available by resource reference" do
+        @catalog.add_resource(@one)
+        @catalog.resource(@one.ref).should equal(@one)
+        @catalog.vertices.find { |r| r.ref == @one.ref }.should equal(@one)
+    end
+
+    it "should canonize how resources are referred to during retrieval when both type and title are provided" do
+        @catalog.add_resource(@one)
+
+        @catalog.resource("me", "one").should equal(@one)
+    end
+
+    it "should canonize how resources are referred to during retrieval when just the title is provided" do
+        @catalog.add_resource(@one)
+
+        @catalog.resource("me[one]", nil).should equal(@one)
+    end
+
+    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
+
+    it "should not store objects that do not respond to :ref" do
+        proc { @catalog.add_resource("thing") }.should raise_error(ArgumentError)
+    end
+
+    it "should remove all resources when asked" do
+        @catalog.add_resource @one
+        @catalog.add_resource @two
+        @one.expects :remove
+        @two.expects :remove
+        @catalog.clear(true)
+    end
+
+    it "should support a mechanism for finishing resources" do
+        @one.expects :finish
+        @two.expects :finish
+        @catalog.add_resource @one
+        @catalog.add_resource @two
+
+        @catalog.finalize
+    end
+
+    it "should make default resources when finalizing" do
+        @catalog.expects(:make_default_resources)
+        @catalog.finalize
+    end
+
+    it "should add default resources to the catalog upon creation" do
+        @catalog.make_default_resources
+        @catalog.resource(:schedule, "daily").should_not be_nil
+    end
+    
+    it "should optionally support an initialization block and should finalize after such blocks" do
+        @one.expects :finish
+        @two.expects :finish
+        config = Puppet::Node::Catalog.new("host") do |conf|
+            conf.add_resource @one
+            conf.add_resource @two
+        end
+    end
+
+    it "should inform the resource that it is the resource's catalog" do
+        @one.expects(:catalog=).with(@catalog)
+        @catalog.add_resource @one
+    end
+
+    it "should be able to find resources by reference" do
+        @catalog.add_resource @one
+        @catalog.resource(@one.ref).should equal(@one)
+    end
+
+    it "should be able to find resources by reference or by type/title tuple" do
+        @catalog.add_resource @one
+        @catalog.resource("me", "one").should equal(@one)
+    end
+
+    it "should have a mechanism for removing resources" do
+        @catalog.add_resource @one
+        @one.expects :remove
+        @catalog.remove_resource(@one)
+        @catalog.resource(@one.ref).should be_nil
+        @catalog.vertex?(@one).should be_false
+    end
+
+    it "should have a method for creating aliases for resources" do
+        @catalog.add_resource @one
+        @catalog.alias(@one, "other")
+        @catalog.resource("me", "other").should equal(@one)
+    end
+
+    # This test is the same as the previous, but the behaviour should be explicit.
+    it "should alias using the class name from the resource reference, not the resource class name" do
+        @catalog.add_resource @one
+        @catalog.alias(@one, "other")
+        @catalog.resource("me", "other").should equal(@one)
+    end
+
+    it "should fail to add an alias if the aliased name already exists" do
+        @catalog.add_resource @one
+        proc { @catalog.alias @two, "one" }.should raise_error(ArgumentError)
+    end
+
+    it "should not fail when a resource has duplicate aliases created" do
+        @catalog.add_resource @one
+        proc { @catalog.alias @one, "one" }.should_not raise_error
+    end
+
+    it "should be able to look resources up by their aliases" do
+        @catalog.add_resource @one
+        @catalog.alias @one, "two"
+        @catalog.resource(:me, "two").should equal(@one)
+    end
+
+    it "should remove resource aliases when the target resource is removed" do
+        @catalog.add_resource @one
+        @catalog.alias(@one, "other")
+        @one.expects :remove
+        @catalog.remove_resource(@one)
+        @catalog.resource("me", "other").should be_nil
+    end
+
+    it "should add an alias for the namevar when the title and name differ on isomorphic resource types" do
+        resource = Puppet::Type.type(:file).create :path => "/something", :title => "other", :content => "blah"
+        resource.expects(:isomorphic?).returns(true)
+        @catalog.add_resource(resource)
+        @catalog.resource(:file, "other").should equal(resource)
+        @catalog.resource(:file, "/something").ref.should == resource.ref
+    end
+
+    it "should not add an alias for the namevar when the title and name differ on non-isomorphic resource types" do
+        resource = Puppet::Type.type(:file).create :path => "/something", :title => "other", :content => "blah"
+        resource.expects(:isomorphic?).returns(false)
+        @catalog.add_resource(resource)
+        @catalog.resource(:file, resource.title).should equal(resource)
+        # We can't use .should here, because the resources respond to that method.
+        if @catalog.resource(:file, resource.name)
+            raise "Aliased non-isomorphic resource"
+        end
+    end
+
+    after do
+        Puppet::Type.allclear
+    end
+end
+
+describe Puppet::Node::Catalog do
+    before :each do
+        @catalog = Puppet::Node::Catalog.new("host")
+
+        @catalog.retrieval_duration = Time.now
+        @transaction = mock 'transaction'
+        Puppet::Transaction.stubs(:new).returns(@transaction)
+        @transaction.stubs(:evaluate)
+        @transaction.stubs(:cleanup)
+        @transaction.stubs(:addtimes)
+    end
+
+    describe Puppet::Node::Catalog, " when applying" do
+
+        it "should create and evaluate a transaction" do
+            @transaction.expects(:evaluate)
+            @catalog.apply
+        end
+
+        it "should provide the catalog time to the transaction" do
+            @transaction.expects(:addtimes).with do |arg|
+                arg[:config_retrieval].should be_instance_of(Time)
+                true
+            end
+            @catalog.apply
+        end
+
+        it "should clean up the transaction" do
+            @transaction.expects :cleanup
+            @catalog.apply
+        end
+    
+        it "should return the transaction" do
+            @catalog.apply.should equal(@transaction)
+        end
+
+        it "should yield the transaction if a block is provided" do
+            @catalog.apply do |trans|
+                trans.should equal(@transaction)
+            end
+        end
+    
+        it "should default to not being a host catalog" do
+            @catalog.host_config.should be_nil
+        end
+
+        it "should pass supplied tags on to the transaction" do
+            @transaction.expects(:tags=).with(%w{one two})
+            @catalog.apply(:tags => %w{one two})
+        end
+
+        it "should set ignoreschedules on the transaction if specified in apply()" do
+            @transaction.expects(:ignoreschedules=).with(true)
+            @catalog.apply(:ignoreschedules => true)
+        end
+    end
+
+    describe Puppet::Node::Catalog, " when applying host catalogs" do
+
+        # super() doesn't work in the setup method for some reason
+        before do
+            @catalog.host_config = true
+        end
+
+        it "should send a report if reporting is enabled" do
+            Puppet[:report] = true
+            @transaction.expects :send_report
+            @transaction.stubs :any_failed? => false
+            @catalog.apply
+        end
+
+        it "should send a report if report summaries are enabled" do
+            Puppet[:summarize] = true
+            @transaction.expects :send_report
+            @transaction.stubs :any_failed? => false
+            @catalog.apply
+        end
+
+        it "should initialize the state database before applying a catalog" do
+            Puppet::Util::Storage.expects(:load)
+
+            # Short-circuit the apply, so we know we're loading before the transaction
+            Puppet::Transaction.expects(:new).raises ArgumentError
+            proc { @catalog.apply }.should raise_error(ArgumentError)
+        end
+
+        it "should sync the state database after applying" do
+            Puppet::Util::Storage.expects(:store)
+            @transaction.stubs :any_failed? => false
+            @catalog.apply
+        end
+
+        after { Puppet.settings.clear }
+    end
+
+    describe Puppet::Node::Catalog, " when applying non-host catalogs" do
+
+        before do
+            @catalog.host_config = false
+        end
+    
+        it "should never send reports" do
+            Puppet[:report] = true
+            Puppet[:summarize] = true
+            @transaction.expects(:send_report).never
+            @catalog.apply
+        end
+
+        it "should never modify the state database" do
+            Puppet::Util::Storage.expects(:load).never
+            Puppet::Util::Storage.expects(:store).never
+            @catalog.apply
+        end
+
+        after { Puppet.settings.clear }
+    end
+end
+
+describe Puppet::Node::Catalog, " when creating a relationship graph" do
+    before do
+        Puppet::Type.type(:component)
+        @catalog = Puppet::Node::Catalog.new("host")
+        @compone = Puppet::Type::Component.create :name => "one"
+        @comptwo = Puppet::Type::Component.create :name => "two", :require => ["class", "one"]
+        @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
+
+        @three = @file.create :path => "/three"
+        @four = @file.create :path => "/four", :require => ["file", "/three"]
+        @five = @file.create :path => "/five"
+        @catalog.add_resource @compone, @comptwo, @one, @two, @three, @four, @five
+        @relationships = @catalog.relationship_graph
+    end
+
+    it "should fail when trying to create a relationship graph for a relationship graph" do
+        proc { @relationships.relationship_graph }.should raise_error(Puppet::DevError)
+    end
+
+    it "should be able to create a relationship graph" do
+        @relationships.should be_instance_of(Puppet::Node::Catalog)
+    end
+
+    it "should copy its host_config setting to the relationship graph" do
+        config = Puppet::Node::Catalog.new
+        config.host_config = true
+        config.relationship_graph.host_config.should be_true
+    end
+
+    it "should not have any components" do
+        @relationships.vertices.find { |r| r.instance_of?(Puppet::Type::Component) }.should be_nil
+    end
+
+    it "should have all non-component resources from the catalog" do
+        # The failures print out too much info, so i just do a class comparison
+        @relationships.vertex?(@five).should be_true
+    end
+
+    it "should have all resource relationships set as edges" do
+        @relationships.edge?(@three, @four).should be_true
+    end
+
+    it "should copy component relationships to all contained resources" do
+        @relationships.edge?(@one, @two).should be_true
+    end
+
+    it "should get removed when the catalog is cleaned up" do
+        @relationships.expects(:clear).with(false)
+        @catalog.clear
+        @catalog.instance_variable_get("@relationship_graph").should be_nil
+    end
+
+    it "should create a new relationship graph after clearing the old one" do
+        @relationships.expects(:clear).with(false)
+        @catalog.clear
+        @catalog.relationship_graph.should be_instance_of(Puppet::Node::Catalog)
+    end
+
+    it "should look up resources in the relationship graph if not found in the main catalog" do
+        five = stub 'five', :ref => "File[five]", :catalog= => nil
+        @relationships.add_resource five
+        @catalog.resource(five.ref).should equal(five)
+    end
+
+    it "should provide a method to create additional resources that also registers the resource" do
+        args = {:name => "/yay", :ensure => :file}
+        resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog
+        Puppet::Type.type(:file).expects(:create).with(args).returns(resource)
+        @catalog.create_resource :file, args
+        @catalog.resource("File[/yay]").should equal(resource)
+    end
+
+    it "should provide a mechanism for creating implicit resources" do
+        args = {:name => "/yay", :ensure => :file}
+        resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog
+        Puppet::Type.type(:file).expects(:create).with(args).returns(resource)
+        resource.expects(:implicit=).with(true)
+        @catalog.create_implicit_resource :file, args
+        @catalog.resource("File[/yay]").should equal(resource)
+    end
+
+    it "should add implicit resources to the relationship graph if there is one" do
+        args = {:name => "/yay", :ensure => :file}
+        resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog
+        resource.expects(:implicit=).with(true)
+        Puppet::Type.type(:file).expects(:create).with(args).returns(resource)
+        # build the graph
+        relgraph = @catalog.relationship_graph
+
+        @catalog.create_implicit_resource :file, args
+        relgraph.resource("File[/yay]").should equal(resource)
+    end
+
+    it "should remove resources created mid-transaction" do
+        args = {:name => "/yay", :ensure => :file}
+        resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog
+        @transaction = mock 'transaction'
+        Puppet::Transaction.stubs(:new).returns(@transaction)
+        @transaction.stubs(:evaluate)
+        @transaction.stubs(:cleanup)
+        @transaction.stubs(:addtimes)
+        Puppet::Type.type(:file).expects(:create).with(args).returns(resource)
+        resource.expects :remove
+        @catalog.apply do |trans|
+            @catalog.create_resource :file, args
+            @catalog.resource("File[/yay]").should equal(resource)
+        end
+        @catalog.resource("File[/yay]").should be_nil
+    end
+
+    it "should remove resources from the relationship graph if it exists" do
+        @catalog.remove_resource(@one)
+        @catalog.relationship_graph.vertex?(@one).should be_false
+    end
+
+    after do
+        Puppet::Type.allclear
+    end
+end
+
+describe Puppet::Node::Catalog, " when writing dot files" do
+    before do
+        @catalog = Puppet::Node::Catalog.new("host")
+        @name = :test
+        @file = File.join(Puppet[:graphdir], @name.to_s + ".dot")
+    end
+    it "should only write when it is a host catalog" do
+        File.expects(:open).with(@file).never
+        @catalog.host_config = false
+        Puppet[:graph] = true
+        @catalog.write_graph(@name)
+    end
+
+    it "should only write when graphing is enabled" do
+        File.expects(:open).with(@file).never
+        @catalog.host_config = true
+        Puppet[:graph] = false
+        @catalog.write_graph(@name)
+    end
+
+    it "should write a dot file based on the passed name" do
+        File.expects(:open).with(@file, "w").yields(stub("file", :puts => nil))
+        @catalog.expects(:to_dot).with("name" => @name.to_s.capitalize)
+        @catalog.host_config = true
+        Puppet[:graph] = true
+        @catalog.write_graph(@name)
+    end
+
+    after do
+        Puppet.settings.clear
+    end
+end
+
+describe Puppet::Node::Catalog, " when indirecting" do
+    before do
+        @indirection = stub 'indirection', :name => :catalog
+
+        Puppet::Indirector::Indirection.clear_cache
+    end
+
+    it "should redirect to the indirection for retrieval" do
+        Puppet::Node::Catalog.stubs(:indirection).returns(@indirection)
+        @indirection.expects(:find)
+        Puppet::Node::Catalog.find(:myconfig)
+    end
+
+    it "should default to the 'compiler' terminus" do
+        Puppet::Node::Catalog.indirection.terminus_class.should == :compiler
+    end
+
+    after do
+        mocha_verify
+        Puppet::Indirector::Indirection.clear_cache
+    end
+end
+
+describe Puppet::Node::Catalog, " when converting to yaml" do
+    before do
+        @catalog = Puppet::Node::Catalog.new("me")
+        @catalog.add_edge("one", "two")
+    end
+
+    it "should be able to be dumped to yaml" do
+        YAML.dump(@catalog).should be_instance_of(String)
+    end
+end
+
+describe Puppet::Node::Catalog, " when converting from yaml" do
+    before do
+        @catalog = Puppet::Node::Catalog.new("me")
+        @catalog.add_edge("one", "two")
+
+        text = YAML.dump(@catalog)
+        @newcatalog = YAML.load(text)
+    end
+
+    it "should get converted back to a catalog" do
+        @newcatalog.should be_instance_of(Puppet::Node::Catalog)
+    end
+
+    it "should have all vertices" do
+        @newcatalog.vertex?("one").should be_true
+        @newcatalog.vertex?("two").should be_true
+    end
+
+    it "should have all edges" do
+        @newcatalog.edge?("one", "two").should be_true
+    end
+end
diff --git a/spec/unit/node/environment.rb b/spec/unit/node/environment.rb
new file mode 100755
index 0000000..8433a98
--- /dev/null
+++ b/spec/unit/node/environment.rb
@@ -0,0 +1,89 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/node/environment'
+
+describe Puppet::Node::Environment do
+    it "should provide a list of valid environments" do
+        Puppet::Node::Environment.valid.should be_instance_of(Array)
+    end
+
+    it "should determine its list of valid environments from splitting the :environments setting on commas" do
+        Puppet.settings.stubs(:value).with(:environments).returns("one,two")
+        Puppet::Node::Environment.valid.collect { |e| e.to_s }.sort.should == %w{one two}.sort
+    end
+
+    it "should not use an environment when determining the list of valid environments" do
+        Puppet.settings.expects(:value).with(:environments).returns("one,two")
+        Puppet::Node::Environment.valid
+    end
+
+    it "should provide a means of identifying invalid environments" do
+        Puppet.settings.expects(:value).with(:environments).returns("one,two")
+        Puppet::Node::Environment.valid?(:three).should be_false
+    end
+
+    it "should provide a means of identifying valid environments" do
+        Puppet.settings.expects(:value).with(:environments).returns("one,two")
+        Puppet::Node::Environment.valid?(:one).should be_true
+    end
+
+    it "should be used to determine when an environment setting is valid" do
+        Puppet.settings.expects(:value).with(:environments).returns("one,two")
+        proc { Puppet.settings[:environment] = :three }.should raise_error(ArgumentError)
+    end
+
+    it "should use the default environment if no name is provided while initializing an environment" do
+        Puppet.settings.expects(:value).with(:environments).returns("one,two")
+        Puppet.settings.expects(:value).with(:environment).returns("one")
+        Puppet::Node::Environment.new().name.should == :one
+    end
+
+    it "should treat environment instances as singletons" do
+        Puppet.settings.stubs(:value).with(:environments).returns("one")
+        Puppet::Node::Environment.new("one").should equal(Puppet::Node::Environment.new("one"))
+    end
+
+    it "should treat an environment specified as names or strings as equivalent" do
+        Puppet.settings.stubs(:value).with(:environments).returns("one")
+        Puppet::Node::Environment.new(:one).should equal(Puppet::Node::Environment.new("one"))
+    end
+
+    it "should fail if an invalid environment instance is asked for" do
+        Puppet.settings.stubs(:value).with(:environments).returns("one,two")
+        proc { Puppet::Node::Environment.new("three") }.should raise_error(ArgumentError)
+    end
+
+    it "should consider environments that are empty strings invalid" do
+        Puppet::Node::Environment.valid?("").should be_false
+    end
+
+    it "should fail if a no-longer-valid environment instance is asked for" do
+        Puppet.settings.expects(:value).with(:environments).returns("one")
+        Puppet::Node::Environment.new("one")
+        Puppet.settings.expects(:value).with(:environments).returns("two")
+        proc { Puppet::Node::Environment.new("one") }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Node::Environment, " when modeling a specific environment" do
+    before do
+        Puppet.settings.expects(:value).with(:environments).returns("testing")
+    end
+
+    it "should have a method for returning the environment name" do
+        Puppet::Node::Environment.new("testing").name.should == :testing
+    end
+
+    it "should provide an array-like accessor method for returning any environment-specific setting" do
+        env = Puppet::Node::Environment.new("testing")
+        env.should respond_to(:[])
+    end
+
+    it "should ask the Puppet settings instance for the setting qualified with the environment name" do
+        Puppet.settings.expects(:value).with("myvar", :testing).returns("myval")
+        env = Puppet::Node::Environment.new("testing")
+        env["myvar"].should == "myval"
+    end
+end
diff --git a/spec/unit/node/facts.rb b/spec/unit/node/facts.rb
new file mode 100755
index 0000000..1bfccd3
--- /dev/null
+++ b/spec/unit/node/facts.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/node/facts'
+
+describe Puppet::Node::Facts, " when indirecting" do
+    before do
+        @indirection = stub 'indirection', :request => mock('request'), :name => :facts
+
+        # We have to clear the cache so that the facts ask for our indirection stub,
+        # instead of anything that might be cached.
+        Puppet::Indirector::Indirection.clear_cache
+        @facts = Puppet::Node::Facts.new("me", "one" => "two")
+    end
+
+    it "should redirect to the specified fact store for retrieval" do
+        Puppet::Node::Facts.stubs(:indirection).returns(@indirection)
+        @indirection.expects(:find)
+        Puppet::Node::Facts.find(:my_facts)
+    end
+
+    it "should redirect to the specified fact store for storage" do
+        Puppet::Node::Facts.stubs(:indirection).returns(@indirection)
+        @indirection.expects(:save)
+        @facts.save
+    end
+
+    it "should default to the 'facter' terminus" do
+        Puppet::Node::Facts.indirection.terminus_class.should == :facter
+    end
+
+    after do
+        mocha_verify
+        Puppet::Indirector::Indirection.clear_cache
+    end
+end
+
+describe Puppet::Node::Facts, " when storing and retrieving" do
+    it "should add metadata to the facts" do
+        facts = Puppet::Node::Facts.new("me", "one" => "two", "three" => "four")
+        facts.values[:_timestamp].should be_instance_of(Time)
+    end
+end
diff --git a/spec/unit/other/checksum.rb b/spec/unit/other/checksum.rb
new file mode 100755
index 0000000..6a63e83
--- /dev/null
+++ b/spec/unit/other/checksum.rb
@@ -0,0 +1,92 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-22.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/checksum'
+
+describe Puppet::Checksum do
+    it "should have 'Checksum' and the checksum algorithm when converted to a string" do
+        inst = Puppet::Checksum.new("whatever", "md5")
+        inst.to_s.should == "Checksum<{md5}#{inst.checksum}>"
+    end
+
+    it "should convert algorithm names to symbols when they are set after checksum creation" do
+        sum = Puppet::Checksum.new("whatever")
+        sum.algorithm = "md5"
+        sum.algorithm.should == :md5
+    end
+
+    it "should return the checksum as the name" do
+        sum = Puppet::Checksum.new("whatever")
+        sum.checksum.should == sum.name
+    end
+end
+
+describe Puppet::Checksum, " when initializing" do
+    before do
+        @content = "this is some content"
+        @sum = Puppet::Checksum.new(@content)
+    end
+
+    it "should require content" do
+        proc { Puppet::Checksum.new(nil) }.should raise_error(ArgumentError)
+    end
+
+    it "should set the content appropriately" do
+        @sum.content.should == @content
+    end
+
+    it "should calculate the checksum" do
+        require 'digest/md5'
+        Digest::MD5.expects(:hexdigest).with(@content).returns(:mychecksum)
+        @sum.checksum.should == :mychecksum
+    end
+
+    it "should not calculate the checksum until it is asked for" do
+        require 'digest/md5'
+        Digest::MD5.expects(:hexdigest).never
+        sum = Puppet::Checksum.new(@content, :md5)
+    end
+
+    it "should remove the old checksum value if the algorithm is changed" do
+        Digest::MD5.expects(:hexdigest).with(@content).returns(:oldsum)
+        oldsum = @sum.checksum
+        @sum.algorithm = :sha1
+        Digest::SHA1.expects(:hexdigest).with(@content).returns(:newsum)
+        @sum.checksum.should == :newsum
+    end
+
+    it "should default to 'md5' as the checksum algorithm if the algorithm is not in the name" do
+        @sum.algorithm.should == :md5
+    end
+
+    it "should support specifying the algorithm during initialization" do
+        sum = Puppet::Checksum.new(@content, :sha1)
+        sum.algorithm.should == :sha1
+    end
+
+    it "should fail when an unsupported algorithm is used" do
+        proc { Puppet::Checksum.new(@content, :nope) }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Checksum, " when using back-ends" do
+    it "should redirect using Puppet::Indirector" do
+        Puppet::Indirector::Indirection.instance(:checksum).model.should equal(Puppet::Checksum)
+    end
+
+    it "should have a :save instance method" do
+        Puppet::Checksum.new("mysum").should respond_to(:save)
+    end
+
+    it "should respond to :find" do
+        Puppet::Checksum.should respond_to(:find)
+    end
+
+    it "should respond to :destroy" do
+        Puppet::Checksum.should respond_to(:destroy)
+    end
+end
diff --git a/spec/unit/other/pgraph.rb b/spec/unit/other/pgraph.rb
new file mode 100755
index 0000000..10ab934
--- /dev/null
+++ b/spec/unit/other/pgraph.rb
@@ -0,0 +1,210 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-12.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/pgraph'
+require 'puppet/util/graph'
+
+class Container
+    include Puppet::Util::Graph
+    include Enumerable
+    attr_accessor :name
+    def each
+        @children.each do |c| yield c end
+    end
+    
+    def initialize(name, ary)
+        @name = name
+        @children = ary
+    end
+    
+    def push(*ary)
+        ary.each { |c| @children.push(c)}
+    end
+    
+    def to_s
+        @name
+    end
+end
+
+describe Puppet::PGraph do
+    before do
+        @graph = Puppet::PGraph.new
+    end
+
+    it "should correctly clear vertices and edges when asked" do
+	    @graph.add_edge("a", "b")
+	    @graph.add_vertex "c"
+        @graph.clear
+        @graph.vertices.should be_empty
+        @graph.edges.should be_empty
+    end
+end
+
+describe Puppet::PGraph, " when matching edges" do
+    before do
+        @graph = Puppet::PGraph.new
+	    @event = Puppet::Event.new(:source => "a", :event => :yay)
+	    @none = Puppet::Event.new(:source => "a", :event => :NONE)
+
+	    @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"])
+    end
+
+    it "should match edges whose source matches the source of the event" do
+	    @graph.matching_edges([@event]).should == [@edges["a/b"]]
+    end
+
+    it "should match always match nothing when the event is :NONE" do
+	    @graph.matching_edges([@none]).should be_empty
+    end
+
+    it "should match multiple edges" do
+	    @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"])
+    end
+end
+
+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")
+    end
+
+    it "should find all dependents when they are on multiple levels" do
+        @graph.dependents("a").sort.should == %w{b c d}.sort
+    end
+
+    it "should find single dependents" do
+        @graph.dependents("b").sort.should == %w{d}.sort
+    end
+
+    it "should return an empty array when there are no dependents" do
+        @graph.dependents("c").sort.should == [].sort
+    end
+
+    it "should find all dependencies when they are on multiple levels" do
+        @graph.dependencies("d").sort.should == %w{a b}
+    end
+
+    it "should find single dependencies" do
+        @graph.dependencies("c").sort.should == %w{a}
+    end
+    
+    it "should return an empty array when there are no dependencies" do
+        @graph.dependencies("a").sort.should == []
+    end
+end
+
+describe Puppet::PGraph, " when splicing the relationship graph" do
+    def container_graph
+        @one = Container.new("one", %w{a b})
+        @two = Container.new("two", ["c", "d"])
+        @three = Container.new("three", ["i", "j"])
+        @middle = Container.new("middle", ["e", "f", @two])
+        @top = Container.new("top", ["g", "h", @middle, @one, @three])
+        @empty = Container.new("empty", [])
+
+        @contgraph = @top.to_graph
+
+        # We have to add the container to the main graph, else it won't
+        # be spliced in the dependency graph.
+        @contgraph.add_vertex(@empty)
+    end
+
+    def dependency_graph
+        @depgraph = Puppet::PGraph.new
+        @contgraph.vertices.each do |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)
+        end
+    end
+
+    def splice
+        @depgraph.splice!(@contgraph, Container)
+    end
+
+    before do
+        container_graph
+        dependency_graph
+        splice
+    end
+
+    # This is the real heart of splicing -- replacing all containers in
+    # our relationship and exploding their relationships so that each
+    # relationship to a container gets copied to all of its children.
+    it "should remove all Container objects from the dependency graph" do
+        @depgraph.vertices.find_all { |v| v.is_a?(Container) }.should be_empty
+    end
+
+    it "should add container relationships to contained objects" do
+        @contgraph.leaves(@middle).each do |leaf|
+            @depgraph.should be_edge("h", leaf)
+        end
+    end
+
+    it "should explode container-to-container relationships, making edges between all respective contained objects" do
+        @one.each do |oobj|
+            @two.each do |tobj|
+                @depgraph.should be_edge(oobj, tobj)
+            end
+        end
+    end
+
+    it "should no longer contain anything but the non-container objects" do
+        @depgraph.vertices.find_all { |v| ! v.is_a?(String) }.should be_empty
+    end
+
+    it "should copy labels" do
+        @depgraph.edges.each do |edge|
+            edge.label.should == {:callback => :refresh}
+        end
+    end
+
+    it "should not add labels to edges that have none" do
+        @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})
+        splice
+        # And make sure the label got copied.
+        @depgraph.edge_label("c", "i").should == {:callback => :refresh}
+    end
+
+    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})
+        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})
+        splice
+        @three.each do |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
+    end
+end
diff --git a/spec/unit/other/transaction.rb b/spec/unit/other/transaction.rb
new file mode 100755
index 0000000..0db470d
--- /dev/null
+++ b/spec/unit/other/transaction.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/transaction'
+
+describe Puppet::Transaction, " when determining tags" do
+    before do
+        @config = Puppet::Node::Catalog.new
+        @transaction = Puppet::Transaction.new(@config)
+    end
+
+    it "should default to the tags specified in the :tags setting" do
+        Puppet.expects(:[]).with(:tags).returns("one")
+        @transaction.tags.should == %w{one}
+    end
+
+    it "should split tags based on ','" do
+        Puppet.expects(:[]).with(:tags).returns("one,two")
+        @transaction.tags.should == %w{one two}
+    end
+
+    it "should use any tags set after creation" do
+        Puppet.expects(:[]).with(:tags).never
+        @transaction.tags = %w{one two}
+        @transaction.tags.should == %w{one two}
+    end
+
+    it "should always convert assigned tags to an array" do
+        @transaction.tags = "one::two"
+        @transaction.tags.should == %w{one::two}
+    end
+end
diff --git a/spec/unit/other/transbucket.rb b/spec/unit/other/transbucket.rb
new file mode 100755
index 0000000..4494f2a
--- /dev/null
+++ b/spec/unit/other/transbucket.rb
@@ -0,0 +1,172 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::TransBucket do
+    before do
+        @bucket = Puppet::TransBucket.new
+    end
+
+    it "should be able to produce a RAL component" do
+        @bucket.name = "luke"
+        @bucket.type = "user"
+
+        resource = nil
+        proc { resource = @bucket.to_type }.should_not raise_error
+        resource.should be_instance_of(Puppet::Type::Component)
+        resource.title.should == "User[luke]"
+    end
+
+    it "should accept TransObjects into its children list" do
+        object = Puppet::TransObject.new("luke", "user")
+        proc { @bucket.push(object) }.should_not raise_error
+        @bucket.each do |o|
+            o.should equal(object)
+        end
+    end
+
+    it "should accept TransBuckets into its children list" do
+        object = Puppet::TransBucket.new()
+        proc { @bucket.push(object) }.should_not raise_error
+        @bucket.each do |o|
+            o.should equal(object)
+        end
+    end
+
+    it "should refuse to accept any children that are not TransObjects or TransBuckets" do
+        proc { @bucket.push "a test" }.should raise_error
+    end
+
+    it "should return use 'node' as the type and the provided name as the title if only a type is provided" do
+        @bucket.type = "mystuff"
+        @bucket.to_ref.should == "Node[mystuff]"
+    end
+
+    it "should return use 'component' as the type and the provided type as the title if only a name is provided" do
+        @bucket.name = "mystuff"
+        @bucket.to_ref.should == "Class[mystuff]"
+    end
+
+    it "should return nil as its reference when type and name are missing" do
+        @bucket.to_ref.should be_nil
+    end
+
+    it "should return the title as its reference" do
+        @bucket.name = "luke"
+        @bucket.type = "user"
+        @bucket.to_ref.should == "User[luke]"
+    end
+
+    it "should canonize resource references when the type is 'component'" do
+        @bucket.name = 'something'
+        @bucket.type = 'foo::bar'
+
+        @bucket.to_ref.should == "Foo::Bar[something]"
+    end
+end
+
+describe Puppet::TransBucket, " when generating a catalog" do
+    before do
+        @bottom = Puppet::TransBucket.new
+        @bottom.type = "fake"
+        @bottom.name = "bottom"
+        @bottomobj = Puppet::TransObject.new("bottom", "user")
+        @bottom.push @bottomobj
+
+        @middle = Puppet::TransBucket.new
+        @middle.type = "fake"
+        @middle.name = "middle"
+        @middleobj = Puppet::TransObject.new("middle", "user")
+        @middle.push(@middleobj)
+        @middle.push(@bottom)
+
+        @top = Puppet::TransBucket.new
+        @top.type = "fake"
+        @top.name = "top"
+        @topobj = Puppet::TransObject.new("top", "user")
+        @top.push(@topobj)
+        @top.push(@middle)
+
+        @users = %w{top middle bottom}
+        @fakes = %w{Fake[bottom] Fake[middle] Fake[top]}
+    end
+
+    after do
+        Puppet::Type.allclear
+    end
+
+    it "should convert all transportable objects to RAL resources" do
+        @catalog = @top.to_catalog
+        @users.each do |name|
+            @catalog.vertices.find { |r| r.class.name == :user and r.title == name }.should be_instance_of(Puppet::Type.type(:user))
+        end
+    end
+
+    it "should fail if any transportable resources fail to convert to RAL resources" do
+        @bottomobj.expects(:to_type).raises ArgumentError
+        lambda { @bottom.to_catalog }.should raise_error(ArgumentError)
+    end
+
+    it "should convert all transportable buckets to RAL components" do
+        @catalog = @top.to_catalog
+        @fakes.each do |name|
+            @catalog.vertices.find { |r| r.class.name == :component and r.title == name }.should be_instance_of(Puppet::Type.type(:component))
+        end
+    end
+
+    it "should add all resources to the graph's resource table" do
+        @catalog = @top.to_catalog
+        @catalog.resource("fake[top]").should equal(@top)
+    end
+
+    it "should finalize all resources" do
+        @catalog = @top.to_catalog
+        @catalog.vertices.each do |vertex| vertex.should be_finalized end
+    end
+
+    it "should only call to_type on each resource once" do
+        # We just raise exceptions here because we're not interested in
+        # what happens with the result, only that the method only
+        # gets called once.
+        resource = @topobj.to_type
+        @topobj.expects(:to_type).once.returns resource
+        @top.to_catalog
+    end
+
+    it "should set each TransObject's catalog before converting to a RAL resource" do
+        @middleobj.expects(:catalog=).with { |c| c.is_a?(Puppet::Node::Catalog) }
+        @top.to_catalog
+    end
+
+    it "should set each TransBucket's catalog before converting to a RAL resource" do
+        # each bucket is seen twice in the loop, so we have to handle the case where the config
+        # is set twice
+        @bottom.expects(:catalog=).with { |c| c.is_a?(Puppet::Node::Catalog) }.at_least_once
+        @top.to_catalog
+    end
+end
+
+describe Puppet::TransBucket, " when serializing" do
+    before do
+        @bucket = Puppet::TransBucket.new(%w{one two})
+        @bucket.name = "one"
+        @bucket.type = "two"
+    end
+
+    it "should be able to be dumped to yaml" do
+        proc { YAML.dump(@bucket) }.should_not raise_error
+    end
+
+    it "should dump YAML that produces an equivalent object" do
+        result = YAML.dump(@bucket)
+
+        newobj = YAML.load(result)
+        newobj.name.should == "one"
+        newobj.type.should == "two"
+        children = []
+        newobj.each do |o|
+            children << o
+        end
+        children.should == %w{one two}
+    end
+end
diff --git a/spec/unit/other/transobject.rb b/spec/unit/other/transobject.rb
new file mode 100755
index 0000000..07ffdf8
--- /dev/null
+++ b/spec/unit/other/transobject.rb
@@ -0,0 +1,86 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/transportable'
+
+describe Puppet::TransObject do
+    it "should canonize resource references" do
+        resource = Puppet::TransObject.new("me", "foo::bar")
+        resource.ref.should == 'Foo::Bar[me]'
+    end
+
+    it "should lower-case resource types for backward compatibility with 0.23.2" do
+        resource = Puppet::TransObject.new("me", "Foo")
+        resource.type.should == 'foo'
+    end
+end
+
+describe Puppet::TransObject, " when serializing" do
+    before do
+        @resource = Puppet::TransObject.new("/my/file", "file")
+        @resource["one"] = "test"
+        @resource["two"] = "other"
+    end
+
+    it "should be able to be dumped to yaml" do
+        proc { YAML.dump(@resource) }.should_not raise_error
+    end
+
+    it "should produce an equivalent yaml object" do
+        text = YAML.dump(@resource)
+
+        newresource = YAML.load(text)
+        newresource.name.should == "/my/file"
+        newresource.type.should == "file"
+        %w{one two}.each do |param|
+            newresource[param].should == @resource[param]
+        end
+    end
+end
+
+describe Puppet::TransObject, " when converting to a RAL resource" do
+    before do
+        @resource = Puppet::TransObject.new("/my/file", "file")
+        @resource["one"] = "test"
+        @resource["two"] = "other"
+    end
+
+    it "should use the resource type's :create method to create the resource" do
+        type = mock 'resource type'
+        type.expects(:create).with(@resource).returns(:myresource)
+        Puppet::Type.expects(:type).with("file").returns(type)
+        @resource.to_type.should == :myresource
+    end
+
+    it "should convert to a component instance if the resource type cannot be found" do
+        Puppet::Type.expects(:type).with("file").returns(nil)
+        @resource.expects(:to_component).returns(:mycomponent)
+        @resource.to_type.should == :mycomponent
+    end
+end
+
+describe Puppet::TransObject, " when converting to a RAL component instance" do
+    before do
+        @resource = Puppet::TransObject.new("/my/file", "one::two")
+        @resource["one"] = "test"
+        @resource["noop"] = "other"
+    end
+
+    it "should use a new TransObject whose name is a resource reference of the type and title of the original TransObject" do
+        Puppet::Type::Component.expects(:create).with { |resource| resource.type == "component" and resource.name == "One::Two[/my/file]" }.returns(:yay)
+        @resource.to_component.should == :yay
+    end
+
+    it "should pass the resource parameters on to the newly created TransObject" do
+        Puppet::Type::Component.expects(:create).with { |resource| resource["noop"] == "other" }.returns(:yay)
+        @resource.to_component.should == :yay
+    end
+
+    # LAK:FIXME This really isn't the design we want going forward, but it's
+    # good enough for now.
+    it "should not pass resource paramaters that are not metaparams" do
+        Puppet::Type::Component.expects(:create).with { |resource| resource["one"].nil? }.returns(:yay)
+        @resource.to_component.should == :yay
+    end
+end
diff --git a/spec/unit/parser/ast/definition.rb b/spec/unit/parser/ast/definition.rb
new file mode 100755
index 0000000..a58e4d0
--- /dev/null
+++ b/spec/unit/parser/ast/definition.rb
@@ -0,0 +1,195 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::Definition, "when initializing" do
+end
+
+describe Puppet::Parser::AST::Definition, "when evaluating" do
+    before do
+        @type = Puppet::Parser::Resource
+        @parser = Puppet::Parser::Parser.new :Code => ""
+        @source = @parser.newclass ""
+        @definition = @parser.newdefine "mydefine"
+        @node = Puppet::Node.new("yaynode")
+        @compiler = Puppet::Parser::Compiler.new(@node, @parser)
+        @scope = @compiler.topscope
+
+        @resource = Puppet::Parser::Resource.new(:type => "mydefine", :title => "myresource", :scope => @scope, :source => @source)
+    end
+
+    it "should create a new scope" do
+        scope = nil
+        code = mock 'code'
+        code.expects(:safeevaluate).with do |scope|
+            scope.object_id.should_not == @scope.object_id
+            true
+        end
+        @definition.stubs(:code).returns(code)
+        @definition.evaluate_code(@resource)
+    end
+
+#    it "should copy its namespace to the scope"
+#
+#    it "should mark the scope virtual if the resource is virtual"
+#
+#    it "should mark the scope exported if the resource is exported"
+#
+#    it "should set the resource's parameters as variables in the scope"
+#
+#    it "should set the resource's title as a variable in the scope"
+#
+#    it "should copy the resource's title in a 'name' variable in the scope"
+#
+#    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 old_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 oldtest_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 oldtest_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 oldtest_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 0000000..0abc174
--- /dev/null
+++ b/spec/unit/parser/ast/hostclass.rb
@@ -0,0 +1,135 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::HostClass do
+    before :each do
+        @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
+
+    describe Puppet::Parser::AST::HostClass, "when evaluating" do
+
+        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 return the existing resource when not creating a new one" do
+            @compiler.catalog.expects(:resource).with(:class, "top").returns("something")
+            @compiler.catalog.expects(:add_resource).never
+            @top.evaluate(@scope).should == "something"
+        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
+
+        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
+end
diff --git a/spec/unit/parser/ast/node.rb b/spec/unit/parser/ast/node.rb
new file mode 100755
index 0000000..aaba4c2
--- /dev/null
+++ b/spec/unit/parser/ast/node.rb
@@ -0,0 +1,125 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::AST::Node do
+    before :each do
+        @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
+
+    describe Puppet::Parser::AST::Node, "when evaluating" do
+
+        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
+
+        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
+end
diff --git a/spec/unit/parser/collector.rb b/spec/unit/parser/collector.rb
new file mode 100755
index 0000000..e1ceb23
--- /dev/null
+++ b/spec/unit/parser/collector.rb
@@ -0,0 +1,417 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/parser/collector'
+
+describe Puppet::Parser::Collector, "when initializing" do
+    before do
+        @scope = mock 'scope'
+        @resource_type = 'resource_type'
+        @form = :exported
+        @vquery = mock 'vquery'
+        @equery = mock 'equery'
+
+        @collector = Puppet::Parser::Collector.new(@scope, @resource_type, @equery, @vquery, @form)
+    end
+
+    it "should require a scope" do
+        @collector.scope.should equal(@scope)
+    end
+
+    it "should require a resource type" do
+        @collector.type.should == 'Resource_type'
+    end
+
+    it "should only accept :virtual or :exported as the collector form" do
+        proc { @collector = Puppet::Parser::Collector.new(@scope, @resource_type, @vquery, @equery, :other) }.should raise_error(ArgumentError)
+    end
+
+    it "should accept an optional virtual query" do
+        @collector.vquery.should equal(@vquery)
+    end
+
+    it "should accept an optional exported query" do
+        @collector.equery.should equal(@equery)
+    end
+
+    it "should canonize the type name" do
+        @collector = Puppet::Parser::Collector.new(@scope, "resource::type", @equery, @vquery, @form)
+        @collector.type.should == "Resource::Type"
+    end
+end
+
+describe Puppet::Parser::Collector, "when collecting specific virtual resources" do
+    before do
+        @scope = mock 'scope'
+        @resource_type = mock 'resource_type'
+        @vquery = mock 'vquery'
+        @equery = mock 'equery'
+
+        @collector = Puppet::Parser::Collector.new(@scope, @resource_type, @equery, @vquery, :virtual)
+    end
+
+    it "should not fail when it does not find any resources to collect" do
+        @collector.resources = ["File[virtual1]", "File[virtual2]"]
+        @scope.stubs(:findresource).returns(false)
+        proc { @collector.evaluate }.should_not raise_error
+    end
+
+    it "should mark matched resources as non-virtual" do
+        @collector.resources = ["File[virtual1]", "File[virtual2]"]
+        one = mock 'one'
+        one.expects(:virtual=).with(false)
+        @scope.stubs(:findresource).with("File[virtual1]").returns(one)
+        @scope.stubs(:findresource).with("File[virtual2]").returns(nil)
+        @collector.evaluate
+    end
+
+    it "should return matched resources" do
+        @collector.resources = ["File[virtual1]", "File[virtual2]"]
+        one = mock 'one'
+        one.stubs(:virtual=)
+        @scope.stubs(:findresource).with("File[virtual1]").returns(one)
+        @scope.stubs(:findresource).with("File[virtual2]").returns(nil)
+        @collector.evaluate.should == [one]
+    end
+
+    it "should delete itself from the compile's collection list if it has found all of its resources" do
+        @collector.resources = ["File[virtual1]"]
+        one = mock 'one'
+        one.stubs(:virtual=)
+        @compiler.expects(:delete_collection).with(@collector)
+        @scope.expects(:compiler).returns(@compiler)
+        @scope.stubs(:findresource).with("File[virtual1]").returns(one)
+        @collector.evaluate
+    end
+
+    it "should not delete itself from the compile's collection list if it has unfound resources" do
+        @collector.resources = ["File[virtual1]"]
+        one = mock 'one'
+        one.stubs(:virtual=)
+        @compiler.expects(:delete_collection).never
+        @scope.stubs(:findresource).with("File[virtual1]").returns(nil)
+        @collector.evaluate
+    end
+end
+
+describe Puppet::Parser::Collector, "when collecting virtual resources" do
+    before do
+        @scope = mock 'scope'
+        @compiler = mock 'compile'
+        @scope.stubs(:compiler).returns(@compiler)
+        @resource_type = "Mytype"
+        @vquery = proc { |res| true }
+
+        @collector = Puppet::Parser::Collector.new(@scope, @resource_type, nil, @vquery, :virtual)
+    end
+
+    it "should find all resources matching the vquery" do
+        one = stub 'one', :type => "Mytype", :virtual? => true
+        two = stub 'two', :type => "Mytype", :virtual? => true
+
+        one.stubs(:virtual=)
+        two.stubs(:virtual=)
+
+        @compiler.expects(:resources).returns([one, two])
+
+        @collector.evaluate.should == [one, two]
+    end
+
+    it "should mark all matched resources as non-virtual" do
+        one = stub 'one', :type => "Mytype", :virtual? => true
+
+        one.expects(:virtual=).with(false)
+
+        @compiler.expects(:resources).returns([one])
+
+        @collector.evaluate
+    end
+
+    it "should return matched resources" do
+        one = stub 'one', :type => "Mytype", :virtual? => true
+        two = stub 'two', :type => "Mytype", :virtual? => true
+
+        one.stubs(:virtual=)
+        two.stubs(:virtual=)
+
+        @compiler.expects(:resources).returns([one, two])
+
+        @collector.evaluate.should == [one, two]
+    end
+
+    it "should return all resources of the correct type if there is no virtual query" do
+        one = stub 'one', :type => "Mytype", :virtual? => true
+        two = stub 'two', :type => "Mytype", :virtual? => true
+
+        one.expects(:virtual=).with(false)
+        two.expects(:virtual=).with(false)
+
+        @compiler.expects(:resources).returns([one, two])
+
+        @collector = Puppet::Parser::Collector.new(@scope, @resource_type, nil, nil, :virtual)
+
+        @collector.evaluate.should == [one, two]
+    end
+
+    it "should not return or mark resources of a different type" do
+        one = stub 'one', :type => "Mytype", :virtual? => true
+        two = stub 'two', :type => :other, :virtual? => true
+
+        one.expects(:virtual=).with(false)
+        two.expects(:virtual=).never
+
+        @compiler.expects(:resources).returns([one, two])
+
+        @collector.evaluate.should == [one]
+    end
+
+    it "should not return or mark non-virtual resources" do
+        one = stub 'one', :type => "Mytype", :virtual? => false
+        two = stub 'two', :type => :other, :virtual? => false
+
+        one.expects(:virtual=).never
+        two.expects(:virtual=).never
+
+        @compiler.expects(:resources).returns([one, two])
+
+        @collector.evaluate.should be_false
+    end
+
+    it "should not return or mark non-matching resources" do
+        @collector.vquery = proc { |res| res.name == :one }
+
+        one = stub 'one', :name => :one, :type => "Mytype", :virtual? => true
+        two = stub 'two', :name => :two, :type => "Mytype", :virtual? => true
+
+        one.expects(:virtual=).with(false)
+        two.expects(:virtual=).never
+
+        @compiler.expects(:resources).returns([one, two])
+
+        @collector.evaluate.should == [one]
+    end
+end
+
+describe Puppet::Parser::Collector, "when collecting exported resources" do
+    confine Puppet.features.rails? => "Cannot test Rails integration without ActiveRecord"
+
+    before do
+        @scope = stub 'scope', :host => "myhost", :debug => nil
+        @compiler = mock 'compile'
+        @scope.stubs(:compiler).returns(@compiler)
+        @resource_type = "Mytype"
+        @equery = "test = true"
+        @vquery = proc { |r| true }
+
+        @collector = Puppet::Parser::Collector.new(@scope, @resource_type, @equery, @vquery, :exported)
+    end
+
+    # Stub most of our interface to Rails.
+    def stub_rails(everything = false)
+        ActiveRecord::Base.stubs(:connected?).returns(false)
+        Puppet::Rails.stubs(:init)
+        if everything
+            Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+            Puppet::Rails::Resource.stubs(:find).returns([])
+        end
+    end
+
+    it "should use initialize the Rails support if ActiveRecord is not connected" do
+        @compiler.stubs(:resources).returns([])
+        ActiveRecord::Base.expects(:connected?).returns(false)
+        Puppet::Rails.expects(:init)
+        Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+        Puppet::Rails::Resource.stubs(:find).returns([])
+
+        @collector.evaluate
+    end
+
+    it "should return all matching resources from the current compile" do
+        stub_rails(true)
+
+        one = stub 'one', :type => "Mytype", :virtual? => true, :exported? => true
+        two = stub 'two', :type => "Mytype", :virtual? => true, :exported? => true
+
+        one.stubs(:exported=)
+        one.stubs(:virtual=)
+        two.stubs(:exported=)
+        two.stubs(:virtual=)
+
+        @compiler.expects(:resources).returns([one, two])
+
+        @collector.evaluate.should == [one, two]
+    end
+
+    it "should mark all returned resources as not virtual" do
+        stub_rails(true)
+
+        one = stub 'one', :type => "Mytype", :virtual? => true, :exported? => true
+
+        one.stubs(:exported=)
+        one.expects(:virtual=).with(false)
+
+        @compiler.expects(:resources).returns([one])
+
+        @collector.evaluate.should == [one]
+    end
+
+    it "should convert all found resources into parser resources" do
+        stub_rails()
+        Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+
+        one = stub 'one', :restype => "Mytype", :title => "one", :virtual? => true, :exported? => true
+        Puppet::Rails::Resource.stubs(:find).returns([one])
+
+        resource = mock 'resource'
+        one.expects(:to_resource).with(@scope).returns(resource)
+        resource.stubs(:exported=)
+        resource.stubs(:virtual=)
+
+        @compiler.stubs(:resources).returns([])
+        @scope.stubs(:findresource).returns(nil)
+
+        @compiler.stubs(:add_resource)
+
+        @collector.evaluate.should == [resource]
+    end
+
+    it "should store converted resources in the compile's resource list" do
+        stub_rails()
+        Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+
+        one = stub 'one', :restype => "Mytype", :title => "one", :virtual? => true, :exported? => true
+        Puppet::Rails::Resource.stubs(:find).returns([one])
+
+        resource = mock 'resource'
+        one.expects(:to_resource).with(@scope).returns(resource)
+        resource.stubs(:exported=)
+        resource.stubs(:virtual=)
+
+        @compiler.stubs(:resources).returns([])
+        @scope.stubs(:findresource).returns(nil)
+
+        @compiler.expects(:add_resource).with(@scope, resource)
+
+        @collector.evaluate.should == [resource]
+    end
+
+    # This way one host doesn't store another host's resources as exported.
+    it "should mark resources collected from the database as not exported" do
+        stub_rails()
+        Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+
+        one = stub 'one', :restype => "Mytype", :title => "one", :virtual? => true, :exported? => true
+        Puppet::Rails::Resource.stubs(:find).returns([one])
+
+        resource = mock 'resource'
+        one.expects(:to_resource).with(@scope).returns(resource)
+        resource.expects(:exported=).with(false)
+        resource.stubs(:virtual=)
+
+        @compiler.stubs(:resources).returns([])
+        @scope.stubs(:findresource).returns(nil)
+
+        @compiler.stubs(:add_resource)
+
+        @collector.evaluate
+    end
+
+    it "should fail if an equivalent resource already exists in the compile" do
+        stub_rails()
+        Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+
+        rails = stub 'one', :restype => "Mytype", :title => "one", :virtual? => true, :exported? => true, :id => 1, :ref => "yay"
+        inmemory = stub 'one', :type => "Mytype", :virtual? => true, :exported? => true, :rails_id => 2
+
+        Puppet::Rails::Resource.stubs(:find).returns([rails])
+
+        resource = mock 'resource'
+
+        @compiler.stubs(:resources).returns([])
+        @scope.stubs(:findresource).returns(inmemory)
+
+        @compiler.stubs(:add_resource)
+
+        proc { @collector.evaluate }.should raise_error(Puppet::ParseError)
+    end
+
+    it "should ignore exported resources that match already-collected resources" do
+        stub_rails()
+        Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+
+        rails = stub 'one', :restype => "Mytype", :title => "one", :virtual? => true, :exported? => true, :id => 1, :ref => "yay"
+        inmemory = stub 'one', :type => "Mytype", :virtual? => true, :exported? => true, :rails_id => 1
+
+        Puppet::Rails::Resource.stubs(:find).returns([rails])
+
+        resource = mock 'resource'
+
+        @compiler.stubs(:resources).returns([])
+        @scope.stubs(:findresource).returns(inmemory)
+
+        @compiler.stubs(:add_resource)
+
+        proc { @collector.evaluate }.should_not raise_error(Puppet::ParseError)
+    end
+end
+
+describe Puppet::Parser::Collector, "when building its ActiveRecord query for collecting exported resources" do
+    confine Puppet.features.rails? => "Cannot test Rails integration without ActiveRecord"
+
+    before do
+        @scope = stub 'scope', :host => "myhost", :debug => nil
+        @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)
+        @compiler.stubs(:resources).returns([])
+
+        ActiveRecord::Base.stubs(:connected?).returns(false)
+
+        Puppet::Rails.stubs(:init)
+        Puppet::Rails::Host.stubs(:find_by_name).returns(nil)
+        Puppet::Rails::Resource.stubs(:find).returns([])
+    end
+
+    it "should exclude all resources from the host if ActiveRecord contains information for this host" do
+        @host = mock 'host'
+        @host.stubs(:id).returns 5
+
+        Puppet::Rails::Host.expects(:find_by_name).with(@scope.host).returns(@host)
+
+        Puppet::Rails::Resource.stubs(:find).with { |*arguments|
+            options = arguments[3]
+            options[:conditions][0] =~ /^host_id != \?/ and options[:conditions][1] == 5 
+        }.returns([])
+
+        @collector.evaluate
+    end
+
+    it "should return parameter names and parameter values when querying ActiveRecord" do
+        Puppet::Rails::Resource.stubs(:find).with { |*arguments|
+            options = arguments[3]
+            options[:include] == {:param_values => :param_name}
+        }.returns([])
+
+        @collector.evaluate
+    end
+
+    it "should only search for exported resources with the matching type" do
+        Puppet::Rails::Resource.stubs(:find).with { |*arguments|
+            options = arguments[3]
+            options[:conditions][0].include?("(exported=? AND restype=?)") and options[:conditions][1] == true and options[:conditions][2] == "Mytype"
+        }.returns([])
+    end
+
+    it "should include the export query if one is provided" do
+        @collector = Puppet::Parser::Collector.new(@scope, @resource_type, "test = true", @vquery, :exported)
+        Puppet::Rails::Resource.stubs(:find).with { |*arguments|
+            options = arguments[3]
+            options[:conditions][0].include?("test = true")
+        }.returns([])
+    end
+end
diff --git a/spec/unit/parser/compiler.rb b/spec/unit/parser/compiler.rb
new file mode 100755
index 0000000..ab430da
--- /dev/null
+++ b/spec/unit/parser/compiler.rb
@@ -0,0 +1,532 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Parser::Compiler do
+    before :each do
+        @node = Puppet::Node.new "testnode"
+        @parser = Puppet::Parser::Parser.new :environment => "development"
+
+        @scope_resource = stub 'scope_resource', :builtin? => true, :finish => nil, :ref => 'Class[main]'
+        @scope = stub 'scope', :resource => @scope_resource, :source => mock("source")
+        @compiler = Puppet::Parser::Compiler.new(@node, @parser)
+    end
+
+    describe Puppet::Parser::Compiler do
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+
+        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
+end
diff --git a/spec/unit/parser/interpreter.rb b/spec/unit/parser/interpreter.rb
new file mode 100755
index 0000000..f2526c7
--- /dev/null
+++ b/spec/unit/parser/interpreter.rb
@@ -0,0 +1,159 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Parser::Interpreter do
+    before do
+        @interp = Puppet::Parser::Interpreter.new
+        @parser = mock 'parser'
+    end
+
+    describe "when creating parser instances" do
+        it "should create a parser with code if there is code defined in the :code setting" do
+            Puppet.settings.stubs(:value).with(:code, :myenv).returns("mycode")
+            @parser.expects(:string=).with("mycode")
+            @parser.expects(:parse)
+            Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser)
+            @interp.send(:create_parser, :myenv).object_id.should equal(@parser.object_id)
+        end
+
+        it "should create a parser with the main manifest when the code setting is an empty string" do
+            Puppet.settings.stubs(:value).with(:code, :myenv).returns("")
+            Puppet.settings.stubs(:value).with(:manifest, :myenv).returns("/my/file")
+            @parser.expects(:parse)
+            @parser.expects(:file=).with("/my/file")
+            Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser)
+            @interp.send(:create_parser, :myenv).should equal(@parser)
+        end
+
+        it "should return nothing when new parsers fail" do
+            Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).raises(ArgumentError)
+            proc { @interp.send(:create_parser, :myenv) }.should raise_error(Puppet::Error)
+        end
+
+        it "should create parsers with environment-appropriate manifests" do
+            # Set our per-environment values.  We can't just stub :value, because
+            # it's called by too much of the rest of the code.
+            text = "[env1]\nmanifest = /t/env1.pp\n[env2]\nmanifest = /t/env2.pp"
+            file = mock 'file'
+            file.stubs(:changed?).returns(true)
+            file.stubs(:file).returns("/whatever")
+            Puppet.settings.stubs(:read_file).with(file).returns(text)
+            Puppet.settings.parse(file)
+
+            parser1 = mock 'parser1'
+            Puppet::Parser::Parser.expects(:new).with(:environment => :env1).returns(parser1)
+            parser1.expects(:file=).with("/t/env1.pp")
+            parser1.expects(:parse)
+            @interp.send(:create_parser, :env1)
+
+            parser2 = mock 'parser2'
+            Puppet::Parser::Parser.expects(:new).with(:environment => :env2).returns(parser2)
+            parser2.expects(:file=).with("/t/env2.pp")
+            parser2.expects(:parse)
+            @interp.send(:create_parser, :env2)
+        end
+    end
+
+    describe "when managing parser instances" do
+        it "should use the same parser when the parser does not need reparsing" do
+            @interp.expects(:create_parser).with(:myenv).returns(@parser)
+            @interp.send(:parser, :myenv).should equal(@parser)
+
+            @parser.expects(:reparse?).returns(false)
+            @interp.send(:parser, :myenv).should equal(@parser)
+        end
+
+        it "should fail intelligently if a parser cannot be created and one does not already exist" do
+            @interp.expects(:create_parser).with(:myenv).raises(ArgumentError)
+            proc { @interp.send(:parser, :myenv) }.should raise_error(ArgumentError)
+        end
+
+        it "should use different parsers for different environments" do
+            # get one for the first env
+            @interp.expects(:create_parser).with(:first_env).returns(@parser)
+            @interp.send(:parser, :first_env).should equal(@parser)
+
+            other_parser = mock('otherparser')
+            @interp.expects(:create_parser).with(:second_env).returns(other_parser)
+            @interp.send(:parser, :second_env).should equal(other_parser)
+        end
+
+        describe "when files need reparsing" do
+            it "should create a new parser" do
+                oldparser = mock('oldparser')
+                newparser = mock('newparser')
+                oldparser.expects(:reparse?).returns(true)
+                oldparser.expects(:clear)
+
+                @interp.expects(:create_parser).with(:myenv).returns(oldparser)
+                @interp.send(:parser, :myenv).should equal(oldparser)
+                @interp.expects(:create_parser).with(:myenv).returns(newparser)
+                @interp.send(:parser, :myenv).should equal(newparser)
+            end
+
+            it "should keep the old parser if a new parser cannot be created" do
+                # Get the first parser in the hash.
+                @interp.expects(:create_parser).with(:myenv).returns(@parser)
+                @interp.send(:parser, :myenv).should equal(@parser)
+
+                # Have it indicate something has changed
+                @parser.expects(:reparse?).returns(true)
+
+                # But fail to create a new parser
+                @interp.expects(:create_parser).with(:myenv).raises(ArgumentError)
+
+                # And make sure we still get the old valid parser
+                @interp.send(:parser, :myenv).should equal(@parser)
+            end
+
+            it "should log syntax errors when using the old parser" do
+                # Get the first parser in the hash.
+                @interp.stubs(:create_parser).with(:myenv).returns(@parser)
+                @interp.send(:parser, :myenv)
+
+                # Have it indicate something has changed
+                @parser.stubs(:reparse?).returns(true)
+
+                # But fail to create a new parser
+                @interp.stubs(:create_parser).with(:myenv).raises(ArgumentError)
+
+                Puppet.expects(:err)
+
+                # And make sure we still get the old valid parser
+                @interp.send(:parser, :myenv)
+            end
+        end
+    end
+
+    describe "when compiling a catalog" do
+        before do
+            @node = stub 'node', :environment => :myenv
+            @compiler = mock 'compile'
+        end
+
+        it "should create a compile with the node and parser" do
+            @compiler.expects(:compile).returns(:config)
+            @interp.expects(:parser).with(:myenv).returns(@parser)
+            Puppet::Parser::Compiler.expects(:new).with(@node, @parser).returns(@compiler)
+            @interp.compile(@node)
+        end
+
+        it "should fail intelligently when no parser can be found" do
+            @node.stubs(:name).returns("whatever")
+            @interp.expects(:parser).with(:myenv).returns(nil)
+            proc { @interp.compile(@node) }.should raise_error(Puppet::ParseError)
+        end
+    end
+
+    describe "when returning catalog version" do
+        it "should ask the appropriate parser for the catalog version" do
+            node = mock 'node'
+            node.expects(:environment).returns(:myenv)
+            parser = mock 'parser'
+            parser.expects(:version).returns(:myvers)
+            @interp.expects(:parser).with(:myenv).returns(parser)
+            @interp.configuration_version(node).should equal(:myvers)
+        end
+    end
+end
diff --git a/spec/unit/parser/lexer.rb b/spec/unit/parser/lexer.rb
new file mode 100755
index 0000000..9972f72
--- /dev/null
+++ b/spec/unit/parser/lexer.rb
@@ -0,0 +1,465 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/parser/lexer'
+
+describe Puppet::Parser::Lexer::Token do
+    before do
+        @token = Puppet::Parser::Lexer::Token.new(%r{something}, :NAME)
+    end
+
+    [:regex, :name, :string, :skip, :incr_line, :skip_text].each do |param|
+        it "should have a #{param.to_s} reader" do
+            @token.should be_respond_to(param)
+        end
+
+        it "should have a #{param.to_s} writer" do
+            @token.should be_respond_to(param.to_s + "=")
+        end
+    end
+end
+
+describe Puppet::Parser::Lexer::Token, "when initializing" do
+    it "should create a regex if the first argument is a string" do
+        Puppet::Parser::Lexer::Token.new("something", :NAME).regex.should == %r{something}
+    end
+
+    it "should set the string if the first argument is one" do
+        Puppet::Parser::Lexer::Token.new("something", :NAME).string.should == "something"
+    end
+
+    it "should set the regex if the first argument is one" do
+        Puppet::Parser::Lexer::Token.new(%r{something}, :NAME).regex.should == %r{something}
+    end
+end
+
+describe Puppet::Parser::Lexer::TokenList do
+    before do
+        @list = Puppet::Parser::Lexer::TokenList.new
+    end
+
+    it "should have a method for retrieving tokens by the name" do
+        token = @list.add_token :name, "whatever"
+        @list[:name].should equal(token)
+    end
+
+    it "should have a method for retrieving string tokens by the string" do
+        token = @list.add_token :name, "whatever"
+        @list.lookup("whatever").should equal(token)
+    end
+
+    it "should add tokens to the list when directed" do
+        token = @list.add_token :name, "whatever"
+        @list[:name].should equal(token)
+    end
+
+    it "should have a method for adding multiple tokens at once" do
+        @list.add_tokens "whatever" => :name, "foo" => :bar
+        @list[:name].should_not be_nil
+        @list[:bar].should_not be_nil
+    end
+
+    it "should fail to add tokens sharing a name with an existing token" do
+        @list.add_token :name, "whatever"
+        lambda { @list.add_token :name, "whatever" }.should raise_error(ArgumentError)
+    end
+
+    it "should set provided options on tokens being added" do
+        token = @list.add_token :name, "whatever", :skip_text => true
+        token.skip_text.should == true
+    end
+
+    it "should define any provided blocks as a :convert method" do
+        token = @list.add_token(:name, "whatever")  do "foo" end
+        token.convert.should == "foo"
+    end
+
+    it "should store all string tokens in the :string_tokens list" do
+        one = @list.add_token(:name, "1")
+        @list.string_tokens.should be_include(one)
+    end
+
+    it "should store all regex tokens in the :regex_tokens list" do
+        one = @list.add_token(:name, %r{one})
+        @list.regex_tokens.should be_include(one)
+    end
+
+    it "should not store string tokens in the :regex_tokens list" do
+        one = @list.add_token(:name, "1")
+        @list.regex_tokens.should_not be_include(one)
+    end
+
+    it "should not store regex tokens in the :string_tokens list" do
+        one = @list.add_token(:name, %r{one})
+        @list.string_tokens.should_not be_include(one)
+    end
+
+    it "should sort the string tokens inversely by length when asked" do
+        one = @list.add_token(:name, "1")
+        two = @list.add_token(:other, "12")
+        @list.sort_tokens
+        @list.string_tokens.should == [two, one]
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS do
+    before do
+        @lexer = Puppet::Parser::Lexer.new()
+    end
+
+    {
+        :LBRACK => '[',
+        :RBRACK => ']',
+        :LBRACE => '{',
+        :RBRACE => '}',
+        :LPAREN => '(',
+        :RPAREN => ')', 
+        :EQUALS => '=',
+        :ISEQUAL => '==',
+        :GREATEREQUAL => '>=', 
+        :GREATERTHAN => '>',
+        :LESSTHAN => '<',
+        :LESSEQUAL => '<=',
+        :NOTEQUAL => '!=',
+        :NOT => '!',
+        :COMMA => ',',
+        :DOT => '.',
+        :COLON => ':',
+        :AT => '@',
+        :LLCOLLECT => '<<|',
+        :RRCOLLECT => '|>>',
+        :LCOLLECT => '<|',
+        :RCOLLECT => '|>',
+        :SEMIC => ';',
+        :QMARK => '?',
+        :BACKSLASH => '\\',
+        :FARROW => '=>',
+        :PARROW => '+>'
+    }.each do |name, string|
+        it "should have a token named #{name.to_s}" do
+            Puppet::Parser::Lexer::TOKENS[name].should_not be_nil
+        end
+
+        it "should match '#{string}' for the token #{name.to_s}" do
+            Puppet::Parser::Lexer::TOKENS[name].string.should == string
+        end
+    end
+
+    {
+        "case" => :CASE,
+        "class" => :CLASS,
+        "default" => :DEFAULT,
+        "define" => :DEFINE,
+        "import" => :IMPORT,
+        "if" => :IF,
+        "elsif" => :ELSIF,
+        "else" => :ELSE,
+        "inherits" => :INHERITS,
+        "node" => :NODE,
+        "and"  => :AND,
+        "or"   => :OR,
+        "undef"   => :UNDEF,
+        "false" => :FALSE,
+        "true" => :TRUE
+    }.each do |string, name|
+        it "should have a keyword named #{name.to_s}" do
+            Puppet::Parser::Lexer::KEYWORDS[name].should_not be_nil
+        end
+
+        it "should have the keyword for #{name.to_s} set to #{string}" do
+            Puppet::Parser::Lexer::KEYWORDS[name].string.should == string
+        end
+    end
+
+    # These tokens' strings don't matter, just that the tokens exist.
+    [:DQTEXT, :SQTEXT, :BOOLEAN, :NAME, :NUMBER, :COMMENT, :RETURN, :SQUOTE, :DQUOTE, :VARIABLE].each do |name|
+        it "should have a token named #{name.to_s}" do
+            Puppet::Parser::Lexer::TOKENS[name].should_not be_nil
+        end
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS[:NAME] do
+    before { @token = Puppet::Parser::Lexer::TOKENS[:NAME] }
+
+    it "should match against lower-case alpha-numeric terms" do
+        @token.regex.should =~ "one-two"
+    end
+
+    it "should return itself and the value if the matched term is not a keyword" do
+        Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(nil)
+        @token.convert(stub("lexer"), "myval").should == [Puppet::Parser::Lexer::TOKENS[:NAME], "myval"]
+    end
+
+    it "should return the keyword token and the value if the matched term is a keyword" do
+        keyword = stub 'keyword', :name => :testing
+        Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword)
+        @token.convert(stub("lexer"), "myval").should == [keyword, "myval"]
+    end
+
+    it "should return the BOOLEAN token and 'true' if the matched term is the string 'true'" do
+        keyword = stub 'keyword', :name => :TRUE
+        Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword)
+        @token.convert(stub('lexer'), "true").should == [Puppet::Parser::Lexer::TOKENS[:BOOLEAN], true]
+    end
+
+    it "should return the BOOLEAN token and 'false' if the matched term is the string 'false'" do
+        keyword = stub 'keyword', :name => :FALSE
+        Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword)
+        @token.convert(stub('lexer'), "false").should == [Puppet::Parser::Lexer::TOKENS[:BOOLEAN], false]
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS[:NUMBER] do
+    before { @token = Puppet::Parser::Lexer::TOKENS[:NUMBER] }
+
+    it "should match against numeric terms" do
+        @token.regex.should =~ "2982383139"
+    end
+
+    it "should return the NAME token and the value" do
+        @token.convert(stub("lexer"), "myval").should == [Puppet::Parser::Lexer::TOKENS[:NAME], "myval"]
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS[:COMMENT] do
+    before { @token = Puppet::Parser::Lexer::TOKENS[:COMMENT] }
+
+    it "should match against lines starting with '#'" do
+        @token.regex.should =~ "# this is a comment"
+    end
+
+    it "should be marked to get skipped" do
+        @token.skip?.should be_true
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS[:RETURN] do
+    before { @token = Puppet::Parser::Lexer::TOKENS[:RETURN] }
+
+    it "should match against carriage returns" do
+        @token.regex.should =~ "\n"
+    end
+
+    it "should be marked to initiate text skipping" do
+        @token.skip_text.should be_true
+    end
+
+    it "should be marked to increment the line" do
+        @token.incr_line.should be_true
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS[:SQUOTE] do
+    before { @token = Puppet::Parser::Lexer::TOKENS[:SQUOTE] }
+
+    it "should match against single quotes" do
+        @token.regex.should =~ "'"
+    end
+
+    it "should slurp the rest of the quoted string" do
+        lexer = stub("lexer")
+        lexer.expects(:slurpstring).with("myval").returns("otherval")
+        @token.convert(lexer, "myval")
+    end
+
+    it "should return the SQTEXT token with the slurped string" do
+        lexer = stub("lexer")
+        lexer.stubs(:slurpstring).with("myval").returns("otherval")
+        @token.convert(lexer, "myval").should == [Puppet::Parser::Lexer::TOKENS[:SQTEXT], "otherval"]
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS[:DQUOTE] do
+    before { @token = Puppet::Parser::Lexer::TOKENS[:DQUOTE] }
+
+    it "should match against single quotes" do
+        @token.regex.should =~ '"'
+    end
+
+    it "should slurp the rest of the quoted string" do
+        lexer = stub("lexer")
+        lexer.expects(:slurpstring).with("myval").returns("otherval")
+        @token.convert(lexer, "myval")
+    end
+
+    it "should return the DQTEXT token with the slurped string" do
+        lexer = stub("lexer")
+        lexer.stubs(:slurpstring).with("myval").returns("otherval")
+        @token.convert(lexer, "myval").should == [Puppet::Parser::Lexer::TOKENS[:DQTEXT], "otherval"]
+    end
+end
+
+describe Puppet::Parser::Lexer::TOKENS[:VARIABLE] do
+    before { @token = Puppet::Parser::Lexer::TOKENS[:VARIABLE] }
+
+    it "should match against alpha words prefixed with '$'" do
+        @token.regex.should =~ '$this_var'
+    end
+
+    it "should return the VARIABLE token and the variable name stripped of the '$'" do
+        @token.convert(stub("lexer"), "$myval").should == [Puppet::Parser::Lexer::TOKENS[:VARIABLE], "myval"]
+    end
+end
+
+# FIXME: We need to rewrite all of these tests, but I just don't want to take the time right now.
+describe "Puppet::Parser::Lexer in the old tests" do
+    before { @lexer = Puppet::Parser::Lexer.new }
+
+    it "should do simple lexing" do
+        strings = {
+%q{\\} => [[:BACKSLASH,"\\"],[false,false]],
+%q{simplest scanner test} => [[:NAME,"simplest"],[:NAME,"scanner"],[:NAME,"test"],[false,false]],
+%q{returned scanner test
+} => [[:NAME,"returned"],[:NAME,"scanner"],[:NAME,"test"],[false,false]]
+        }
+        strings.each { |str,ary|
+            @lexer.string = str
+            @lexer.fullscan().should == ary
+        }
+    end
+
+    it "should correctly lex quoted strings" do
+        strings = {
+%q{a simple "scanner" test
+} => [[:NAME,"a"],[:NAME,"simple"],[:DQTEXT,"scanner"],[:NAME,"test"],[false,false]],
+%q{a simple 'single quote scanner' test
+} => [[:NAME,"a"],[:NAME,"simple"],[:SQTEXT,"single quote scanner"],[:NAME,"test"],[false,false]],
+%q{a harder 'a $b \c"'
+} => [[:NAME,"a"],[:NAME,"harder"],[:SQTEXT,'a $b \c"'],[false,false]],
+%q{a harder "scanner test"
+} => [[:NAME,"a"],[:NAME,"harder"],[:DQTEXT,"scanner test"],[false,false]],
+%q{a hardest "scanner \"test\""
+} => [[:NAME,"a"],[:NAME,"hardest"],[:DQTEXT,'scanner "test"'],[false,false]],
+%q{a hardestest "scanner \"test\"
+"
+} => [[:NAME,"a"],[:NAME,"hardestest"],[:DQTEXT,'scanner "test"
+'],[false,false]],
+%q{function("call")} => [[:NAME,"function"],[:LPAREN,"("],[:DQTEXT,'call'],[:RPAREN,")"],[false,false]]
+}
+        strings.each { |str,array|
+            @lexer.string = str
+            @lexer.fullscan().should == array
+        }
+    end
+
+    it "should fail usefully" do
+        strings = %w{
+            ^
+        }
+        strings.each { |str|
+            @lexer.string = str
+            lambda { @lexer.fullscan() }.should raise_error(RuntimeError)
+        }
+    end
+
+    it "should fail if the string is not set" do
+        lambda { @lexer.fullscan() }.should raise_error(Puppet::LexError)
+    end
+
+    it "should correctly identify keywords" do
+        @lexer.string = "case"
+        @lexer.fullscan.should == [[:CASE, "case"], [false, false]]
+    end
+
+    it "should correctly match strings" do
+        names = %w{this is a bunch of names}
+        types = %w{Many Different Words A Word}
+        words = %w{differently Cased words A a}
+
+        names.each { |t|
+            @lexer.string = t
+            @lexer.fullscan.should == [[:NAME,t],[false,false]]
+        }
+        types.each { |t|
+            @lexer.string = t
+            @lexer.fullscan.should == [[:CLASSREF,t],[false,false]]
+        }
+    end
+
+    it "should correctly parse empty strings" do
+        bit = '$var = ""'
+
+        @lexer.string = bit
+
+        lambda { @lexer.fullscan }.should_not raise_error
+    end
+
+    it "should correctly parse virtual resources" do
+        string = "@type {"
+
+        @lexer.string = string
+
+        @lexer.fullscan.should == [[:AT, "@"], [:NAME, "type"], [:LBRACE, "{"], [false,false]]
+    end
+
+    it "should correctly deal with namespaces" do
+        @lexer.string = %{class myclass}
+
+        @lexer.fullscan
+
+        @lexer.namespace.should == "myclass"
+
+        @lexer.namepop
+
+        @lexer.namespace.should == ""
+
+        @lexer.string = "class base { class sub { class more"
+
+        @lexer.fullscan
+
+        @lexer.namespace.should == "base::sub::more"
+
+        @lexer.namepop
+
+        @lexer.namespace.should == "base::sub"
+    end
+
+    it "should correctly handle fully qualified names" do
+        @lexer.string = "class base { class sub::more {"
+
+        @lexer.fullscan
+
+        @lexer.namespace.should == "base::sub::more"
+
+        @lexer.namepop
+
+        @lexer.namespace.should == "base"
+    end
+
+    it "should correctly lex variables" do
+        ["$variable", "$::variable", "$qualified::variable", "$further::qualified::variable"].each do |string|
+            @lexer.string = string
+
+            @lexer.scan do |t, s|
+                t.should == :VARIABLE
+                string.sub(/^\$/, '').should == s
+                break
+            end
+        end
+    end
+
+    # #774
+    it "should correctly parse the CLASSREF token" do
+        string = ["Foo", "::Foo","Foo::Bar","::Foo::Bar"]
+
+        string.each do |foo|
+            @lexer.string = foo
+            @lexer.fullscan[0].should == [:CLASSREF, foo]
+        end
+    end
+end
+
+require 'puppettest/support/utils'
+describe "Puppet::Parser::Lexer in the old tests when lexing example files" do
+    extend PuppetTest
+    extend PuppetTest::Support::Utils
+    textfiles() do |file|
+        it "should correctly lex #{file}" do
+            lexer = Puppet::Parser::Lexer.new()
+            lexer.file = file
+            lambda { lexer.fullscan() }.should_not raise_error
+        end
+    end
+end
diff --git a/spec/unit/parser/resource.rb b/spec/unit/parser/resource.rb
new file mode 100755
index 0000000..6b20219
--- /dev/null
+++ b/spec/unit/parser/resource.rb
@@ -0,0 +1,326 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+# LAK: FIXME This is just new tests for resources; I have
+# not moved all tests over yet.
+
+describe Puppet::Parser::Resource do
+    before do
+        @parser = Puppet::Parser::Parser.new :Code => ""
+        @source = @parser.newclass ""
+        @node = Puppet::Node.new("yaynode")
+        @compiler = Puppet::Parser::Compiler.new(@node, @parser)
+        @scope = @compiler.topscope
+    end
+
+    def mkresource(args = {})
+        args[:source] ||= "source"
+        args[:scope] ||= stub('scope', :source => mock('source'))
+
+        {:type => "resource", :title => "testing", :source => "source", :scope => "scope"}.each do |param, value|
+            args[param] ||= value
+        end
+
+        params = args[:params] || {:one => "yay", :three => "rah"}
+        if args[:params] == :none
+            args.delete(:params)
+        else
+            args[:params] = paramify(args[:source], params)
+        end
+
+        Puppet::Parser::Resource.new(args)
+    end
+
+    def param(name, value, source)
+        Puppet::Parser::Resource::Param.new(:name => name, :value => value, :source => source)
+    end
+
+    def paramify(source, hash)
+        hash.collect do |name, value|
+            Puppet::Parser::Resource::Param.new(
+                :name => name, :value => value, :source => source
+            )
+        end
+    end
+
+    it "should be isomorphic if it is builtin and models an isomorphic type" do
+        Puppet::Type.type(:file).expects(:isomorphic?).returns(true)
+        @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true
+    end
+
+    it "should not be isomorphic if it is builtin and models a non-isomorphic type" do
+        Puppet::Type.type(:file).expects(:isomorphic?).returns(false)
+        @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_false
+    end
+
+    it "should be isomorphic if it is not builtin" do
+        @parser.newdefine "whatever"
+        @resource = Puppet::Parser::Resource.new(:type => "whatever", :title => "whatever", :scope => @scope, :source => @source).isomorphic?.should be_true
+    end
+
+    it "should have a array-indexing method for retrieving parameter values" do
+        @resource = mkresource
+        @resource[:one].should == "yay"
+    end
+
+    it "should have a method for converting to a ral resource" do
+        trans = mock 'trans', :to_type => "yay"
+        @resource = mkresource
+        @resource.expects(:to_trans).returns trans
+        @resource.to_type.should == "yay"
+    end
+
+    describe "when initializing" do
+        before do
+            @arguments = {:type => "resource", :title => "testing", :scope => stub('scope', :source => mock('source'))}
+        end
+
+        [:type, :title, :scope].each do |name|
+            it "should fail unless #{name.to_s} is specified" do
+                try = @arguments.dup
+                try.delete(name)
+                lambda { Puppet::Parser::Resource.new(try) }.should raise_error(ArgumentError)
+            end
+        end
+
+        it "should set the reference correctly" do
+            res = Puppet::Parser::Resource.new(@arguments)
+            res.ref.should == "Resource[testing]"
+        end
+    end
+
+    describe "when evaluating" do
+        before do
+            @type = Puppet::Parser::Resource
+
+            @definition = @parser.newdefine "mydefine"
+            @class = @parser.newclass "myclass"
+            @nodedef = @parser.newnode("mynode")[0]
+        end
+
+        it "should evaluate the associated AST definition" do
+            res = @type.new(:type => "mydefine", :title => "whatever", :scope => @scope, :source => @source)
+            @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_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_code).with(res)
+            res.evaluate
+        end
+    end
+
+    describe "when finishing" do
+        before do
+            @class = @parser.newclass "myclass"
+            @nodedef = @parser.newnode("mynode")[0]
+
+            @resource = Puppet::Parser::Resource.new(:type => "file", :title => "whatever", :scope => @scope, :source => @source)
+        end
+
+        it "should do nothing if it has already been finished" do
+            @resource.finish
+            @resource.expects(:add_metaparams).never
+            @resource.finish
+        end
+
+        it "should add all defaults available from the scope" do
+            @resource.scope.expects(:lookupdefaults).with(@resource.type).returns(:owner => param(:owner, "default", @resource.source))
+            @resource.finish
+
+            @resource[:owner].should == "default"
+        end
+
+        it "should not replace existing parameters with defaults" do
+            @resource.set_parameter :owner, "oldvalue"
+            @resource.scope.expects(:lookupdefaults).with(@resource.type).returns(:owner => :replaced)
+            @resource.finish
+
+            @resource[:owner].should == "oldvalue"
+        end
+
+        it "should add a copy of each default, rather than the actual default parameter instance" do
+            newparam = param(:owner, "default", @resource.source)
+            other = newparam.dup
+            other.value = "other"
+            newparam.expects(:dup).returns(other)
+            @resource.scope.expects(:lookupdefaults).with(@resource.type).returns(:owner => newparam)
+            @resource.finish
+
+            @resource[:owner].should == "other"
+        end
+
+        it "should copy metaparams from its scope" do
+            @scope.setvar("noop", "true")
+
+            @resource.class.publicize_methods(:add_metaparams)  { @resource.add_metaparams }
+
+            @resource["noop"].should == "true"
+        end
+
+        it "should not copy metaparams that it already has" do
+            @resource.set_parameter("noop", "false")
+            @scope.setvar("noop", "true")
+
+            @resource.class.publicize_methods(:add_metaparams)  { @resource.add_metaparams }
+
+            @resource["noop"].should == "false"
+        end
+
+        it "should stack relationship metaparams from its container if it already has them" do
+            @resource.set_parameter("require", "resource")
+            @scope.setvar("require", "container")
+
+            @resource.class.publicize_methods(:add_metaparams)  { @resource.add_metaparams }
+
+            @resource["require"].sort.should == %w{container resource}
+        end
+
+        it "should flatten the array resulting from stacking relationship metaparams" do
+            @resource.set_parameter("require", ["resource1", "resource2"])
+            @scope.setvar("require", %w{container1 container2})
+
+            @resource.class.publicize_methods(:add_metaparams)  { @resource.add_metaparams }
+
+            @resource["require"].sort.should == %w{container1 container2 resource1 resource2}
+        end
+
+        it "should add any tags from the scope resource" do
+            scope_resource = stub 'scope_resource', :tags => %w{one two}
+            @scope.stubs(:resource).returns(scope_resource)
+
+            @resource.class.publicize_methods(:add_scope_tags)  { @resource.add_scope_tags }
+
+            @resource.tags.should be_include("one")
+            @resource.tags.should be_include("two")
+        end
+    end
+
+    describe "when being tagged" do
+        before do
+            @scope_resource = stub 'scope_resource', :tags => %w{srone srtwo}
+            @scope = stub 'scope', :resource => @scope_resource
+            @resource = Puppet::Parser::Resource.new(:type => "file", :title => "yay", :scope => @scope, :source => mock('source'))
+        end
+
+        it "should get tagged with the resource type" do
+            @resource.tags.should be_include("file")
+        end
+
+        it "should get tagged with the title" do
+            @resource.tags.should be_include("yay")
+        end
+
+        it "should get tagged with each name in the title if the title is a qualified class name" do
+            resource = Puppet::Parser::Resource.new(:type => "file", :title => "one::two", :scope => @scope, :source => mock('source'))
+            resource.tags.should be_include("one")
+            resource.tags.should be_include("two")
+        end
+
+        it "should get tagged with each name in the type if the type is a qualified class name" do
+            resource = Puppet::Parser::Resource.new(:type => "one::two", :title => "whatever", :scope => @scope, :source => mock('source'))
+            resource.tags.should be_include("one")
+            resource.tags.should be_include("two")
+        end
+
+        it "should not get tagged with non-alphanumeric titles" do
+            resource = Puppet::Parser::Resource.new(:type => "file", :title => "this is a test", :scope => @scope, :source => mock('source'))
+            resource.tags.should_not be_include("this is a test")
+        end
+
+        it "should fail on tags containing '*' characters" do
+            lambda { @resource.tag("bad*tag") }.should raise_error(Puppet::ParseError)
+        end
+
+        it "should fail on tags starting with '-' characters" do
+            lambda { @resource.tag("-badtag") }.should raise_error(Puppet::ParseError)
+        end
+
+        it "should fail on tags containing ' ' characters" do
+            lambda { @resource.tag("bad tag") }.should raise_error(Puppet::ParseError)
+        end
+
+        it "should allow alpha tags" do
+            lambda { @resource.tag("good_tag") }.should_not raise_error(Puppet::ParseError)
+        end
+    end
+
+    describe "when merging overrides" do
+        before do
+            @source = "source1"
+            @resource = mkresource :source => @source
+            @override = mkresource :source => @source
+        end
+
+        it "should fail when the override was not created by a parent class" do
+            @override.source = "source2"
+            @override.source.expects(:child_of?).with("source1").returns(false)
+            lambda { @resource.merge(@override) }.should raise_error(Puppet::ParseError)
+        end
+
+        it "should succeed when the override was created in the current scope" do
+            @resource.source = "source3"
+            @override.source = @resource.source
+            @override.source.expects(:child_of?).with("source3").never
+            params = {:a => :b, :c => :d}
+            @override.expects(:params).returns(params)
+            @resource.expects(:override_parameter).with(:b)
+            @resource.expects(:override_parameter).with(:d)
+            @resource.merge(@override)
+        end
+
+        it "should succeed when a parent class created the override" do
+            @resource.source = "source3"
+            @override.source = "source4"
+            @override.source.expects(:child_of?).with("source3").returns(true)
+            params = {:a => :b, :c => :d}
+            @override.expects(:params).returns(params)
+            @resource.expects(:override_parameter).with(:b)
+            @resource.expects(:override_parameter).with(:d)
+            @resource.merge(@override)
+        end
+
+        it "should add new parameters when the parameter is not set" do
+            @source.stubs(:child_of?).returns true
+            @override.set_parameter(:testing, "value")
+            @resource.merge(@override)
+
+            @resource[:testing].should == "value"
+        end
+
+        it "should replace existing parameter values" do
+            @source.stubs(:child_of?).returns true
+            @resource.set_parameter(:testing, "old")
+            @override.set_parameter(:testing, "value")
+
+            @resource.merge(@override)
+
+            @resource[:testing].should == "value"
+        end
+
+        it "should add values to the parameter when the override was created with the '+>' syntax" do
+            @source.stubs(:child_of?).returns true
+            param = Puppet::Parser::Resource::Param.new(:name => :testing, :value => "testing", :source => @resource.source)
+            param.add = true
+
+            @override.set_parameter(param)
+
+            @resource.set_parameter(:testing, "other")
+
+            @resource.merge(@override)
+
+            @resource[:testing].should == %w{other testing}
+        end
+
+
+    end
+end
diff --git a/spec/unit/parser/resource/reference.rb b/spec/unit/parser/resource/reference.rb
new file mode 100755
index 0000000..147f772
--- /dev/null
+++ b/spec/unit/parser/resource/reference.rb
@@ -0,0 +1,75 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Parser::Resource::Reference do
+    before do
+        @type = Puppet::Parser::Resource::Reference
+    end
+
+    it "should require a type" do
+        proc { @type.new(:title => "yay") }.should raise_error(Puppet::DevError)
+    end
+
+    it "should require a title" do
+        proc { @type.new(:type => "file") }.should raise_error(Puppet::DevError)
+    end
+
+    it "should know when it refers to a builtin type" do
+        ref = @type.new(:type => "file", :title => "/tmp/yay")
+        ref.builtin?.should be_true
+        ref.builtintype.should equal(Puppet::Type.type(:file))
+    end
+
+    it "should return a downcased relationship-style resource reference for defined types" do
+        ref = @type.new(:type => "file", :title => "/tmp/yay")
+        ref.to_ref.should == ["file", "/tmp/yay"]
+    end
+
+    it "should return a capitalized relationship-style resource reference for defined types" do
+        ref = @type.new(:type => "whatever", :title => "/tmp/yay")
+        ref.to_ref.should == ["Whatever", "/tmp/yay"]
+    end
+
+    it "should return a resource reference string when asked" do
+        ref = @type.new(:type => "file", :title => "/tmp/yay")
+        ref.to_s.should == "File[/tmp/yay]"
+    end
+
+    it "should canonize resource references" do
+        ref = @type.new(:type => "foo::bar", :title => "/tmp/yay")
+        ref.to_s.should == "Foo::Bar[/tmp/yay]"
+    end
+end
+
+describe Puppet::Parser::Resource::Reference, " when modeling defined types" do
+    before do
+        @type = Puppet::Parser::Resource::Reference
+
+        @parser = Puppet::Parser::Parser.new :Code => ""
+        @definition = @parser.newdefine "mydefine"
+        @class = @parser.newclass "myclass"
+        @nodedef = @parser.newnode("mynode")[0]
+        @node = Puppet::Node.new("yaynode")
+
+        @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 => @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 => @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 => @compiler.topscope)
+        ref.builtin?.should be_false
+        ref.definedtype.object_id.should  == @nodedef.object_id
+    end
+end
diff --git a/spec/unit/rails.rb b/spec/unit/rails.rb
new file mode 100755
index 0000000..ad32cac
--- /dev/null
+++ b/spec/unit/rails.rb
@@ -0,0 +1,117 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+require 'puppet/rails'
+
+describe Puppet::Rails, "when initializing any connection" do
+    confine Puppet.features.rails? => "Cannot test without ActiveRecord" 
+
+    it "should use settings" do
+        Puppet.settings.expects(:use).with(:main, :rails, :puppetmasterd)
+        
+        Puppet::Rails.connect
+    end
+    
+    it "should set up a logger with the appropriate Rails log file" do
+        logger = mock 'logger'
+        Logger.expects(:new).with(Puppet[:railslog]).returns(logger)
+        ActiveRecord::Base.expects(:logger=).with(logger)
+        
+        Puppet::Rails.connect
+    end
+    
+    it "should set the log level to whatever the value is in the settings" do
+        Puppet.settings.stubs(:use)
+        Puppet.settings.stubs(:value).with(:rails_loglevel).returns("debug")
+        Puppet.settings.stubs(:value).with(:railslog).returns("/my/file")
+        logger = mock 'logger'
+        Logger.stubs(:new).returns(logger)
+        ActiveRecord::Base.stubs(:logger).returns(logger)
+        logger.expects(:level=).with(Logger::DEBUG)
+
+        ActiveRecord::Base.stubs(:allow_concurrency=)
+        ActiveRecord::Base.stubs(:verify_active_connections!)
+        ActiveRecord::Base.stubs(:establish_connection)
+        Puppet::Rails.stubs(:database_arguments)
+        
+        Puppet::Rails.connect
+    end
+    
+    it "should set ActiveRecord::Base.allow_concurrency" do
+        ActiveRecord::Base.expects(:allow_concurrency=).with(true)
+        
+        Puppet::Rails.connect
+    end
+    
+    it "should call ActiveRecord::Base.verify_active_connections!" do
+        ActiveRecord::Base.expects(:verify_active_connections!)
+        
+        Puppet::Rails.connect
+    end
+    
+    it "should call ActiveRecord::Base.establish_connection with database_arguments" do
+        Puppet::Rails.expects(:database_arguments)
+        ActiveRecord::Base.expects(:establish_connection)
+        
+        Puppet::Rails.connect
+    end
+end
+
+describe Puppet::Rails, "when initializing a sqlite3 connection" do
+    confine Puppet.features.rails? => "Cannot test without ActiveRecord" 
+
+    it "should provide the adapter, log_level, and dbfile arguments" do
+        Puppet.settings.expects(:value).with(:dbadapter).returns("sqlite3")
+        Puppet.settings.expects(:value).with(:rails_loglevel).returns("testlevel")
+        Puppet.settings.expects(:value).with(:dblocation).returns("testlocation")
+        
+        Puppet::Rails.database_arguments.should == {
+            :adapter => "sqlite3",
+            :log_level => "testlevel",
+            :dbfile => "testlocation"
+        }
+    end
+end
+
+describe Puppet::Rails, "when initializing a mysql or postgresql connection" do
+    confine Puppet.features.rails? => "Cannot test without ActiveRecord" 
+
+    it "should provide the adapter, log_level, and host, username, password, and database arguments" do
+        Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
+        Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+        Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+        Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+        Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+        Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+        Puppet.settings.stubs(:value).with(:dbsocket).returns("")
+        
+        Puppet::Rails.database_arguments.should == {
+            :adapter => "mysql",
+            :log_level => "testlevel",
+            :host => "testserver",
+            :username => "testuser",
+            :password => "testpassword",
+            :database => "testname"
+        }
+    end
+    
+    it "should provide the adapter, log_level, and host, username, password, database, and socket arguments" do
+        Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
+        Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+        Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+        Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+        Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+        Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+        Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+        
+        Puppet::Rails.database_arguments.should == {
+            :adapter => "mysql",
+            :log_level => "testlevel",
+            :host => "testserver",
+            :username => "testuser",
+            :password => "testpassword",
+            :database => "testname",
+            :socket => "testsocket"
+        }
+    end
+end
diff --git a/spec/unit/ral/provider/interface/redhat.rb b/spec/unit/ral/provider/interface/redhat.rb
new file mode 100755
index 0000000..9bf1b97
--- /dev/null
+++ b/spec/unit/ral/provider/interface/redhat.rb
@@ -0,0 +1,268 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-11-20.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../../spec_helper'
+
+provider_class = Puppet::Type.type(:interface).provider(:redhat)
+
+describe provider_class do
+    it "should not be functional on systems without a network-scripts directory" do
+        FileTest.expects(:exists?).with("/etc/sysconfig/network-scripts").returns(false)
+        provider_class.should_not be_suitable
+    end
+
+    it "should be functional on systems with a network-scripts directory" do
+        FileTest.expects(:exists?).with("/etc/sysconfig/network-scripts").returns(true)
+        provider_class.should be_suitable
+    end
+end
+
+describe provider_class, " when determining the file path" do
+    it "should always contain '/etc/sysconfig/network-scripts/ifcfg-'" do
+        provider = provider_class.new(:name => "192.168.0.1")
+        provider.file_path.should =~ %r{^/etc/sysconfig/network-scripts/ifcfg-}
+    end
+
+    it "should include the interface name and the description when the interface is an alias" do
+        provider = provider_class.new(:name => "192.168.0.1", :interface => "eth0")
+        provider.interface_type = :alias
+        resource = stub 'resource'
+        resource.stubs(:[]).with(:interface_desc).returns("blah")
+        provider.resource = resource
+        provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-eth0:blah"
+    end
+
+    it "should just include the description when the interface is not an alias" do
+        provider = provider_class.new(:name => "192.168.0.1")
+        provider.interface_type = :normal
+        resource = stub 'resource'
+        resource.stubs(:[]).with(:interface_desc).returns("eth0")
+        provider.resource = resource
+        provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-eth0"
+    end
+
+    it "should use the interface description if one is available" do
+        provider = provider_class.new(:name => "192.168.0.1")
+        provider.interface_type = :normal
+        resource = stub 'resource'
+        resource.stubs(:[]).with(:interface_desc).returns("eth0")
+        provider.resource = resource
+        provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-eth0"
+    end
+
+    it "should use the name if no interface description is available" do
+        provider = provider_class.new(:name => "192.168.0.1")
+        provider.interface_type = :normal
+        provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-192.168.0.1"
+    end
+
+    it "should fail if no name or interface description can be found" do
+        provider = provider_class.new()
+        proc { provider.file_path }.should raise_error
+    end
+end
+
+describe provider_class, " when returning instances" do
+    it "should consider each file in the network-scripts directory an interface instance" do
+        Dir.expects(:glob).with("/etc/sysconfig/network-scripts/ifcfg-*").returns(%w{one two})
+        one = {:name => "one"}
+        two = {:name => "two"}
+        Puppet::Type::Interface::ProviderRedhat.expects(:parse).with("one").returns(one)
+        Puppet::Type::Interface::ProviderRedhat.expects(:parse).with("two").returns(two)
+        Puppet::Type::Interface::ProviderRedhat.expects(:new).with(one).returns(:one)
+        Puppet::Type::Interface::ProviderRedhat.expects(:new).with(two).returns(:two)
+        Puppet::Type::Interface::ProviderRedhat.instances.should == [:one, :two]
+    end
+end
+
+describe provider_class, " when parsing" do
+    it "should return an unmodified provider if the file does not exist" do
+        FileTest.expects(:exist?).with("/my/file").returns(false)
+        provider = mock 'provider'
+        Puppet::Type::Interface::ProviderRedhat.expects(:new).returns(provider)
+        Puppet::Type::Interface::ProviderRedhat.parse("/my/file").should equal(provider)
+    end
+
+    it "should set each attribute in the file on the provider" do
+        FileTest.expects(:exist?).with("/my/file").returns(true)
+        File.expects(:readlines).with("/my/file").returns(%w{one=two three=four})
+        provider = mock 'provider'
+        Puppet::Type::Interface::ProviderRedhat.expects(:new).returns(provider)
+        provider.expects(:one=).with('two')
+        provider.expects(:three=).with('four')
+        Puppet::Type::Interface::ProviderRedhat.parse("/my/file").should equal(provider)
+    end
+end
+
+describe provider_class, " when setting the device to a value containing ':'" do
+    before do
+        @provider = Puppet::Type::Interface::ProviderRedhat.new
+        @provider.device = "one:two"
+    end
+    it "should set the interface type to :alias" do
+        @provider.interface_type.should == :alias
+    end
+    it "should set the interface to the string to the left of the ':'" do
+        @provider.interface.should == "one"
+    end
+    it "should set the ifnum to the string to the right of the ':'" do
+        @provider.ifnum.should == "two"
+    end
+end
+
+describe provider_class, " when setting the device to a value starting with 'dummy-'" do
+    before do
+        @provider = Puppet::Type::Interface::ProviderRedhat.new
+        @provider.device = "dummy5"
+    end
+    it "should set the interface type to :loopback" do
+        @provider.interface_type.should == :loopback
+    end
+    it "should set the interface to 'dummy'" do
+        @provider.interface.should == "dummy"
+    end
+    it "should set the ifnum to remainder of value after removing 'dummy'" do
+        @provider.ifnum.should == "5"
+    end
+end
+
+describe provider_class, " when setting the device to a value containing neither 'dummy-' nor ':'" do
+    before do
+        @provider = Puppet::Type::Interface::ProviderRedhat.new
+        @provider.device = "whatever"
+    end
+    it "should set the interface type to :normal" do
+        @provider.interface_type.should == :normal
+    end
+    it "should set the interface to the device value" do
+        @provider.interface.should == "whatever"
+    end
+end
+
+describe provider_class, " when setting the on_boot value" do
+    before do
+        @provider = Puppet::Type::Interface::ProviderRedhat.new
+    end
+    it "should set it to :true if the value is 'yes'" do
+        @provider.on_boot = "yes"
+        @provider.onboot.should == :true
+    end
+    it "should set it to :false if the value is not 'yes'" do
+        @provider.on_boot = "no"
+        @provider.onboot.should == :false
+    end
+end
+
+describe provider_class, " when setting the ipaddr value" do
+    before do
+        @provider = Puppet::Type::Interface::ProviderRedhat.new
+    end
+
+    it "should set the name to the provided value" do
+        @provider.ipaddr = "yay"
+        @provider.name.should == "yay"
+    end
+end
+
+describe provider_class, " when generating" do
+    before do
+        @provider = Puppet::Type::Interface::ProviderRedhat.new
+        @provider.interface_type = :alias
+        @provider.stubs(:device).returns("mydevice")
+        @provider.stubs(:on_boot).returns("myboot")
+        @provider.stubs(:name).returns("myname")
+        @provider.stubs(:netmask).returns("mynetmask")
+        @provider.interface_type = :alias
+
+        @text = @provider.generate
+    end
+
+    it "should set the bootproto to none if the interface is an alias" do
+        @text.should =~ /^BOOTPROTO=none$/
+    end
+
+    it "should set the bootproto to static if the interface is a loopback" do
+        @provider.interface_type = :loopback
+        @text = @provider.generate
+        @text.should =~ /^BOOTPROTO=static$/
+    end
+
+    it "should set the broadcast address to nothing" do
+        @text.should =~ /^BROADCAST=$/
+    end
+
+    it "should set the netmask to mynetmask" do
+        @text.should =~ /^NETMASK=mynetmask$/
+    end
+
+    it "should set the device to the provider's device" do
+        @text.should =~ /^DEVICE=mydevice$/
+    end
+
+    it "should set the onboot to the provider's on_boot value" do
+        @text.should =~ /^ONBOOT=myboot$/
+    end
+
+    it "should set the ipaddr to the provider's name" do
+        @text.should =~ /^IPADDR=myname$/
+    end
+end
+
+describe provider_class, " when creating and destroying" do
+    before do
+        @provider = provider_class.new(:interface => "eth0", :name => "testing")
+        @path = "/etc/sysconfig/network-scripts/ifcfg-testing"
+    end
+
+    it "should consider the interface present if the file exists" do
+        FileTest.expects(:exist?).with(@path).returns(true)
+        @provider.should be_exists
+    end
+
+    it "should consider the interface absent if the file does not exist" do
+        FileTest.expects(:exist?).with(@path).returns(false)
+        @provider.should_not be_exists
+    end
+
+    it "should remove the file if the interface is being destroyed" do
+        File.expects(:unlink).with(@path)
+        @provider.destroy
+    end
+
+    it "should mark :ensure as :absent if the interface is destroyed" do
+        File.stubs(:unlink)
+        @provider.destroy
+        @provider.ensure.should == :absent
+    end
+
+    it "should mark :ensure as :present if the interface is being created" do
+        resource = stub 'resource', :name => 'testing'
+        resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
+        resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
+        @provider.resource = resource
+        @provider.create
+        @provider.ensure.should == :present
+    end
+
+    it "should write the generated text to disk when the interface is flushed" do
+        fh = mock("filehandle")
+        File.expects(:open).yields(fh)
+        fh.expects(:puts).with("generated")
+        resource = stub 'resource', :name => 'testing'
+        resource.stubs(:[]).with(:interface_desc).returns(nil)
+        resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
+        resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
+        @provider.resource = resource
+        @provider.create
+
+        @provider.stubs(:generate).returns("generated")
+        @provider.flush
+    end
+
+    it "should not write the generated text to disk when the interface is flushed if :ensure == :absent" do
+        @provider.ensure = :absent
+        @provider.flush
+    end
+end
diff --git a/spec/unit/ral/provider/interface/sunos.rb b/spec/unit/ral/provider/interface/sunos.rb
new file mode 100755
index 0000000..7b9f462
--- /dev/null
+++ b/spec/unit/ral/provider/interface/sunos.rb
@@ -0,0 +1,239 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-11-25.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../../spec_helper'
+
+require 'puppet/provider/interface/sunos'
+
+
+provider_class = Puppet::Type.type(:interface).provider(:sunos)
+
+describe provider_class do
+    it "should not be functional on non-SunOS kernels" do
+        Facter.expects(:value).with(:kernel).returns("Linux")
+        provider_class.should_not be_suitable
+    end
+
+    it "should be functional on SunOS kernels" do
+        Facter.expects(:value).with(:kernel).returns("SunOS")
+        provider_class.should be_suitable
+    end
+
+    it "should pick its file path by combining '/etc/hostname.' with the interface if one is set" do
+        provider = provider_class.new(:record_type => :sunos, :interface_type => :normal, :name => "testing", :interface => 'eth0')
+        provider.file_path.should == "/etc/hostname.eth0"
+    end
+
+    it "should pick its file path by combining '/etc/hostname.' with the resource's interface if one is not set in the provider" do
+        provider = provider_class.new(:record_type => :sunos, :interface_type => :normal, :name => "testing")
+        resource = mock 'resource'
+        resource.stubs(:[]).with(:interface).returns("eth0")
+        provider.resource = resource
+        provider.file_path.should == "/etc/hostname.eth0"
+    end
+
+    it "should fail when picking its file path if there is no resource nor an interface set in the provider" do
+        provider = provider_class.new(:record_type => :sunos, :interface_type => :normal, :name => "testing")
+        proc { provider.file_path }.should raise_error(Puppet::Error)
+    end
+end
+
+describe provider_class, " when listing interfaces" do
+    it "should return an instance for every file matching /etc/hostname.*, created with the interface name set from the file" do
+        Dir.expects(:glob).with("/etc/hostname.*").returns(%w{/etc/hostname.one /etc/hostname.two})
+        one_instance = stub 'one_instance', :parse => nil
+        two_instance = stub 'two_instance', :parse => nil
+        provider_class.expects(:new).with(:interface => "one").returns(one_instance)
+        provider_class.expects(:new).with(:interface => "two").returns(two_instance)
+
+        provider_class.instances.should == [one_instance, two_instance]
+    end
+
+    it "should call parse on each instance being returned" do
+        Dir.expects(:glob).with("/etc/hostname.*").returns(%w{/etc/hostname.one})
+        one_instance = mock 'one_instance'
+        provider_class.expects(:new).with(:interface => "one").returns(one_instance)
+
+        one_instance.expects(:parse)
+
+        provider_class.instances
+    end
+
+    it "should assign matching providers to any prefetched instances" do
+        Dir.expects(:glob).with("/etc/hostname.*").returns(%w{one two})
+        one_instance = stub 'one_instance', :name => "one", :parse => nil
+        two_instance = stub 'two_instance', :name => "two", :parse => nil
+        provider_class.expects(:new).with(:interface => "one").returns(one_instance)
+        provider_class.expects(:new).with(:interface => "two").returns(two_instance)
+
+        resources = {"one" => mock("one"), "three" => mock('three')}
+        resources["one"].expects(:provider=).with(one_instance)
+
+        provider_class.prefetch(resources)
+    end
+end
+
+describe provider_class, " when creating and destroying" do
+    before do
+        @provider = provider_class.new(:interface => "eth0", :name => "testing")
+    end
+
+    it "should consider the interface present if the file exists" do
+        FileTest.expects(:exist?).with("/etc/hostname.eth0").returns(true)
+        @provider.should be_exists
+    end
+
+    it "should consider the interface absent if the file does not exist" do
+        FileTest.expects(:exist?).with("/etc/hostname.eth0").returns(false)
+        @provider.should_not be_exists
+    end
+
+    it "should remove the file if the interface is being destroyed" do
+        File.expects(:unlink).with("/etc/hostname.eth0")
+        @provider.destroy
+    end
+
+    it "should mark :ensure as :absent if the interface is destroyed" do
+        File.stubs(:unlink)
+        @provider.destroy
+        @provider.ensure.should == :absent
+    end
+
+    it "should mark :ensure as :present if the interface is being created" do
+        resource = stub 'resource', :name => 'testing'
+        resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
+        resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
+        @provider.resource = resource
+        @provider.create
+        @provider.ensure.should == :present
+    end
+
+    it "should write the generated text to disk when the interface is flushed" do
+        fh = mock("filehandle")
+        File.expects(:open).yields(fh)
+        fh.expects(:print).with("testing\n")
+        resource = stub 'resource', :name => 'testing'
+        resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
+        resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
+        @provider.resource = resource
+        @provider.create
+        @provider.flush
+    end
+
+    it "should not write the generated text to disk when the interface is flushed if :ensure == :absent" do
+        @provider.ensure = :absent
+        @provider.flush
+    end
+end
+
+describe provider_class, " when parsing a non-existant file" do
+    it "should mark the interface as absent" do
+        @provider = provider_class.new(:interface => "eth0", :name => "testing")
+        FileTest.expects(:exist?).with("/etc/hostname.eth0").returns(false)
+        @provider.parse
+        @provider.ensure.should == :absent
+    end
+end
+
+describe provider_class, " when parsing an existing file" do
+    before do
+        @provider = provider_class.new(:interface => "eth0", :name => "testing")
+        FileTest.stubs(:exist?).with("/etc/hostname.eth0").returns(true)
+    end
+
+    def set_text(text)
+        File.stubs(:read).with("/etc/hostname.eth0").returns(text)
+    end
+
+    it "should retain the interface name" do
+        set_text "testing"
+        @provider.parse
+        @provider.ensure.should == :present
+        @provider.interface.should == "eth0"
+    end
+
+    it "should mark the interface as present" do
+        set_text "testing"
+        @provider.parse
+        @provider.ensure.should == :present
+    end
+
+    it "should mark the interface as an alias if the first word is 'addif'" do
+        set_text "addif testing"
+        @provider.parse
+        @provider.interface_type.should == :alias
+    end
+
+    it "should not mark the interface as normal if the first word is not 'addif'" do
+        set_text "testing"
+        @provider.parse
+        @provider.interface_type.should == :normal
+    end
+
+    it "should start the interface on boot of the last word is 'up'" do
+        set_text "testing up"
+        @provider.parse
+        @provider.onboot.should == :true
+    end
+
+    it "should not start the interface on boot of the last word is not 'up'" do
+        set_text "testing"
+        @provider.parse
+        @provider.onboot.should == :false
+    end
+
+    it "should set the interface to the first non-behavioural word" do
+        set_text "addif testing up"
+        @provider.parse
+        @provider.name.should == "testing"
+    end
+
+    it "should consider any remaining terms to be interface options" do
+        set_text "addif testing -O up"
+        @provider.parse
+        @provider.ifopts.should == "-O"
+    end
+end
+
+describe provider_class, " when generating" do
+    before do
+        @provider = provider_class.new(:interface => "eth0", :name => "testing")
+    end
+
+    it "should prefix the text with 'addif' if the interface is an alias" do
+        @provider.interface_type = :alias
+        @provider.generate.should == "addif testing"
+    end
+
+    it "should not prefix the text with 'addif' if the interface is not an alias" do
+        @provider.generate.should == "testing"
+    end
+
+    it "should put the ifopts after the name if they are present" do
+        @provider.ifopts = "-O"
+        @provider.generate.should == "testing -O"
+    end
+
+    it "should mark the interface up if onboot is enabled" do
+        @provider.onboot = :true
+        @provider.generate.should == "testing up"
+    end
+
+    it "should use the resource name if no provider name is present" do
+        provider = provider_class.new(:interface => "eth0")
+        resource = stub 'resource', :name => "rtest"
+        provider.resource = resource
+        provider.generate.should == "rtest"
+    end
+
+    it "should use the provider name if present" do
+        @provider.generate.should == "testing"
+    end
+
+    it "should fail if neither a resource nor the provider name is present" do
+        provider = provider_class.new(:interface => "eth0")
+        proc { provider.generate }.should raise_error
+    end
+end
diff --git a/spec/unit/ral/provider/mount.rb b/spec/unit/ral/provider/mount.rb
new file mode 100755
index 0000000..0b90d53
--- /dev/null
+++ b/spec/unit/ral/provider/mount.rb
@@ -0,0 +1,130 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/provider/mount'
+
+describe Puppet::Provider::Mount do
+    before :each do
+        @mounter = Object.new
+        @mounter.extend(Puppet::Provider::Mount)
+
+        @name = "/"
+
+        @resource = stub 'resource'
+        @resource.stubs(:[]).with(:name).returns(@name)
+
+        @mounter.stubs(:resource).returns(@resource)
+    end
+
+    describe Puppet::Provider::Mount, " when mounting" do
+
+        it "should use the 'mountcmd' method to mount" do
+            @mounter.stubs(:options).returns(nil)
+            @mounter.expects(:mountcmd)
+
+            @mounter.mount
+        end
+
+        it "should flush before mounting if a flush method exists" do
+            @mounter.meta_def(:flush) { }
+            @mounter.expects(:flush)
+            @mounter.stubs(:mountcmd)
+            @mounter.stubs(:options).returns(nil)
+
+            @mounter.mount
+        end
+
+        it "should add the options following '-o' if they exist and are not set to :absent" do
+            @mounter.stubs(:options).returns("ro")
+            @mounter.expects(:mountcmd).with { |*ary| ary[0] == "-o" and ary[1] == "ro" }
+
+            @mounter.mount
+        end
+
+        it "should specify the filesystem name to the mount command" do
+            @mounter.stubs(:options).returns(nil)
+            @mounter.expects(:mountcmd).with { |*ary| ary[-1] == @name }
+
+            @mounter.mount
+        end
+    end
+
+    describe Puppet::Provider::Mount, " when remounting" do
+
+        it "should use '-o remount' if the resource specifies it supports remounting" do
+            @mounter.stubs(:info)
+            @resource.stubs(:[]).with(:remounts).returns(:true)
+            @mounter.expects(:mountcmd).with("-o", "remount", @name)
+            @mounter.remount
+        end
+
+        it "should unmount and mount if the resource does not specify it supports remounting" do
+            @mounter.stubs(:info)
+            @resource.stubs(:[]).with(:remounts).returns(false)
+            @mounter.expects(:unmount)
+            @mounter.expects(:mount)
+            @mounter.remount
+        end
+
+        it "should log that it is remounting" do
+            @resource.stubs(:[]).with(:remounts).returns(:true)
+            @mounter.stubs(:mountcmd)
+            @mounter.expects(:info).with("Remounting")
+            @mounter.remount
+        end
+    end
+
+    describe Puppet::Provider::Mount, " when unmounting" do
+
+        it "should call the :umount command with the resource name" do
+            @mounter.expects(:umount).with(@name)
+            @mounter.unmount
+        end
+    end
+
+    describe Puppet::Provider::Mount, " when determining if it is mounted" do
+
+        it "should parse the results of running the mount command with no arguments" do
+            Facter.stubs(:value).returns("whatever")
+            @mounter.expects(:mountcmd).returns("")
+
+            @mounter.mounted?
+        end
+
+        it "should match ' on /private/var/automount<name>' if the operating system is Darwin" do
+            Facter.stubs(:value).with("operatingsystem").returns("Darwin")
+            @mounter.expects(:mountcmd).returns("/dev/whatever on /private/var/automount/\ndevfs on /dev")
+
+            @mounter.should be_mounted
+        end
+
+        it "should match ' on <name>' if the operating system is Darwin" do
+            Facter.stubs(:value).with("operatingsystem").returns("Darwin")
+            @mounter.expects(:mountcmd).returns("/dev/disk03 on / (local, journaled)\ndevfs on /dev")
+
+            @mounter.should be_mounted
+        end
+
+        it "should match '^<name> on' if the operating system is Solaris" do
+            Facter.stubs(:value).with("operatingsystem").returns("Solaris")
+            @mounter.expects(:mountcmd).returns("/ on /dev/dsk/whatever\n/var on /dev/dsk/other")
+
+            @mounter.should be_mounted
+        end
+
+        it "should match ' on <name>' if the operating system is not Darwin or Solaris" do
+            Facter.stubs(:value).with("operatingsystem").returns("Debian")
+            @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on / and stuff\n/dev/other/disk on /var and stuff")
+
+            @mounter.should be_mounted
+        end
+
+        it "should not be considered mounted if it did not match the mount output" do
+            Facter.stubs(:value).with("operatingsystem").returns("Debian")
+            @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on /something/else and stuff\n/dev/other/disk on /var and stuff")
+
+            @mounter.should_not be_mounted
+        end
+    end
+end
diff --git a/spec/unit/ral/provider/mount/parsed.rb b/spec/unit/ral/provider/mount/parsed.rb
new file mode 100755
index 0000000..21276d9
--- /dev/null
+++ b/spec/unit/ral/provider/mount/parsed.rb
@@ -0,0 +1,185 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-12.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../../../spec_helper'
+
+require 'puppettest/support/utils'
+require 'puppettest/fileparsing'
+
+module ParsedMountTesting
+    include PuppetTest::Support::Utils
+    include PuppetTest::FileParsing
+
+    def fake_fstab
+        os = Facter['operatingsystem']
+        if os == "Solaris"
+            name = "solaris.fstab"
+        elsif os == "FreeBSD"
+            name = "freebsd.fstab"
+        else
+            # Catchall for other fstabs
+            name = "linux.fstab"
+        end
+        oldpath = @provider_class.default_target
+        return fakefile(File::join("data/types/mount", name))
+    end
+
+    def mkmountargs
+        mount = nil
+
+        if defined? @pcount
+            @pcount += 1
+        else
+            @pcount = 1
+        end
+        args = {
+            :name => "/fspuppet%s" % @pcount,
+            :device => "/dev/dsk%s" % @pcount,
+        }
+
+        @provider_class.fields(:parsed).each do |field|
+            unless args.include? field
+                args[field] = "fake%s%s" % [field, @pcount]
+            end
+        end
+
+        return args
+    end
+
+    def mkmount
+        hash = mkmountargs()
+        #hash[:provider] = @provider_class.name
+
+        fakeresource = stub :type => :mount, :name => hash[:name]
+        fakeresource.stubs(:[]).with(:name).returns(hash[:name])
+        fakeresource.stubs(:should).with(:target).returns(nil)
+
+        mount = @provider_class.new(fakeresource)
+        hash[:record_type] = :parsed
+        hash[:ensure] = :present
+        mount.property_hash = hash
+
+        return mount
+    end
+
+    # Here we just create a fake host type that answers to all of the methods
+    # but does not modify our actual system.
+    def mkfaketype
+        @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram))
+    end
+end
+
+provider_class = Puppet::Type.type(:mount).provider(:parsed)
+
+describe provider_class do
+    before :each do
+        @mount_class = Puppet.type(:mount)
+        @provider_class = @mount_class.provider(:parsed)
+    end
+
+
+    describe provider_class do
+        include ParsedMountTesting
+
+        it "should be able to parse all of the example mount tabs" do
+            tab = fake_fstab
+            @provider = @provider_class
+
+            # LAK:FIXME Again, a relatively bad test, but I don't know how to rspec-ify this.
+            # I suppose this is more of an integration test?  I dunno.
+            fakedataparse(tab) do
+                # Now just make we've got some mounts we know will be there
+                hashes = @provider_class.target_records(tab).find_all { |i| i.is_a? Hash }
+                (hashes.length > 0).should be_true
+                root = hashes.find { |i| i[:name] == "/" }
+
+                proc { @provider_class.to_file(hashes) }.should_not raise_error
+            end
+        end
+
+        # LAK:FIXME I can't mock Facter because this test happens at parse-time.
+        it "should default to /etc/vfstab on Solaris and /etc/fstab everywhere else" do
+            should = case Facter.value(:operatingsystem)
+                when "Solaris": "/etc/vfstab"
+                else
+                    "/etc/fstab"
+                end
+            Puppet::Type.type(:mount).provider(:parsed).default_target.should == should
+        end
+    end
+
+    describe provider_class, " when mounting an absent filesystem" do
+        include ParsedMountTesting
+
+        # #730 - Make sure 'flush' is called when a mount is moving from absent to mounted
+        it "should flush the fstab to disk" do
+            mount = mkmount
+
+            # Mark the mount as absent
+            mount.property_hash[:ensure] = :absent
+
+            mount.stubs(:mountcmd) # just so we don't actually try to mount anything
+
+            mount.expects(:flush)
+            mount.mount
+        end
+    end
+
+    describe provider_class, " when modifying the filesystem tab" do
+        include ParsedMountTesting
+        before do
+            @mount = mkmount
+            @target = @provider_class.default_target
+
+            # Never write to disk, only to RAM.
+            @provider_class.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram))
+        end
+
+        it "should write the mount to disk when :flush is called" do
+            @mount.flush
+
+            text = @provider_class.target_object(@provider_class.default_target).read
+            text.should == @mount.class.to_line(@mount.property_hash) + "\n"
+        end
+    end
+
+    describe provider_class, " when parsing information about the root filesystem" do
+        confine "Mount type not tested on Darwin" => Facter["operatingsystem"].value != "Darwin"
+        include ParsedMountTesting
+
+        before do
+            @mount = @mount_class.create :name => "/"
+            @provider = @mount.provider
+        end
+
+        it "should have a filesystem tab" do
+            FileTest.should be_exist(@provider_class.default_target)
+        end
+
+        it "should find the root filesystem" do
+            @provider_class.prefetch("/" => @mount)
+            @mount.provider.property_hash[:ensure].should == :present
+        end
+
+        it "should determine that the root fs is mounted" do
+            @provider_class.prefetch("/" => @mount)
+            @mount.provider.should be_mounted
+        end
+
+        after do
+            Puppet::Type.allclear
+        end
+    end
+
+    describe provider_class, " when mounting and unmounting" do
+        include ParsedMountTesting
+
+        it "should call the 'mount' command to mount the filesystem"
+
+        it "should call the 'unmount' command to unmount the filesystem"
+
+        it "should specify the filesystem when remounting a filesystem"
+    end
+end
diff --git a/spec/unit/ral/type.rb b/spec/unit/ral/type.rb
new file mode 100755
index 0000000..5980167
--- /dev/null
+++ b/spec/unit/ral/type.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Type, " when in a configuration" do
+    before do
+        @catalog = Puppet::Node::Catalog.new
+        @container = Puppet::Type.type(:component).create(:name => "container")
+        @one = Puppet::Type.type(:file).create(:path => "/file/one")
+        @two = Puppet::Type.type(:file).create(:path => "/file/two")
+        @catalog.add_resource @container
+        @catalog.add_resource @one
+        @catalog.add_resource @two
+        @catalog.add_edge @container, @one
+        @catalog.add_edge @container, @two
+    end
+
+    it "should have no parent if there is no in edge" do
+        @container.parent.should be_nil
+    end
+
+    it "should set its parent to its in edge" do
+        @one.parent.ref.should == @container.ref
+    end
+
+    after do
+        @catalog.clear(true)
+    end
+end
diff --git a/spec/unit/ral/type/exec.rb b/spec/unit/ral/type/exec.rb
new file mode 100755
index 0000000..2608042
--- /dev/null
+++ b/spec/unit/ral/type/exec.rb
@@ -0,0 +1,93 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/type/exec'
+
+module ExecModuleTesting
+    def create_resource(command, output, exitstatus)
+        @user_name = 'some_user_name'
+        @group_name = 'some_group_name'
+        Puppet.features.stubs(:root?).returns(true)
+        @execer = Puppet::Type.type(:exec).create(:name => command, :path => %w{/usr/bin /bin}, :user => @user_name, :group => @group_name)
+
+        status = stub "process"
+        status.stubs(:exitstatus).returns(exitstatus)
+
+        Puppet::Util::SUIDManager.expects(:run_and_capture).with([command], @user_name, @group_name).returns([output, status])
+    end
+
+    def create_logging_resource(command, output, exitstatus, logoutput, loglevel)
+        create_resource(command, output, exitstatus)
+        @execer[:logoutput] = logoutput
+        @execer[:loglevel] = loglevel
+    end
+
+    def expect_output(output, loglevel)
+        output.split(/\n/).each do |line|
+            @execer.property(:returns).expects(loglevel).with(line)
+        end
+    end
+end
+
+describe Puppet::Type::Exec, " when execing" do
+    include ExecModuleTesting
+
+    it "should use the 'run_and_capture' method to exec" do
+        command = "true"
+        create_resource(command, "", 0)
+
+        @execer.refresh.should == :executed_command
+    end
+
+    it "should report a failure" do
+        command = "false"
+        create_resource(command, "", 1)
+
+        proc { @execer.refresh }.should raise_error(Puppet::Error)
+    end
+
+    it "should log the output on success" do
+        #Puppet::Util::Log.newdestination :console
+        command = "false"
+        output = "output1\noutput2\n"
+        create_logging_resource(command, output, 0, true, :err)
+        expect_output(output, :err)
+        @execer.refresh
+    end
+
+    it "should log the output on failure" do
+        #Puppet::Util::Log.newdestination :console
+        command = "false"
+        output = "output1\noutput2\n"
+        create_logging_resource(command, output, 1, true, :err)
+        expect_output(output, :err)
+
+        proc { @execer.refresh }.should raise_error(Puppet::Error)
+    end
+
+end
+
+
+describe Puppet::Type::Exec, " when logoutput=>on_failure is set," do
+    include ExecModuleTesting
+
+    it "should log the output on failure" do
+        #Puppet::Util::Log.newdestination :console
+        command = "false"
+        output = "output1\noutput2\n"
+        create_logging_resource(command, output, 1, :on_failure, :err)
+        expect_output(output, :err)
+
+        proc { @execer.refresh }.should raise_error(Puppet::Error)
+    end
+
+    it "shouldn't log the output on success" do
+        #Puppet::Util::Log.newdestination :console
+        command = "true"
+        output = "output1\noutput2\n"
+        create_logging_resource(command, output, 0, :on_failure, :err)
+        @execer.property(:returns).expects(:err).never
+        @execer.refresh
+    end
+end
diff --git a/spec/unit/ral/type/file.rb b/spec/unit/ral/type/file.rb
new file mode 100755
index 0000000..e1a5974
--- /dev/null
+++ b/spec/unit/ral/type/file.rb
@@ -0,0 +1,100 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe Puppet::Type.type(:file) do
+    before do
+        @path = Tempfile.new("puppetspec")
+        @path.close!()
+        @path = @path.path
+        @file = Puppet::Type::File.create(:name => @path)
+    end
+
+    describe "when used with content and replace=>false" do
+        before do
+            @file[:content] = "foo"
+            @file[:replace] = false
+        end
+
+        it "should be insync if the file exists and the content is different" do
+            File.open(@path, "w") do |f| f.puts "bar" end
+            @file.property(:content).insync?("bar").should be_true
+        end
+
+        it "should be insync if the file exists and the content is right" do
+            File.open(@path, "w") do |f| f.puts "foo" end
+            @file.property(:content).insync?("foo").should be_true
+        end
+
+        it "should not be insync if the file does not exist" do
+            @file.property(:content).insync?(:nil).should be_false
+        end
+    end
+
+    describe "when retrieving remote files" do
+        before do
+            @filesource = Puppet::Type::File::FileSource.new
+            @filesource.server = mock 'fileserver'
+
+            @file.stubs(:uri2obj).returns(@filesource)
+
+            @file[:source] = "puppet:///test"
+        end
+
+        it "should fail without writing if it cannot retrieve remote contents" do
+            # create the file, because we only get the problem when it starts
+            # out absent.
+            File.open(@file[:path], "w") { |f| f.puts "a" }
+            @file.expects(:write).never
+
+            @filesource.server.stubs(:describe).returns("493\tfile\t100\t0\t{md5}3f5fef3bddbc4398c46a7bd7ba7b3af7")
+            @filesource.server.stubs(:retrieve).raises(RuntimeError)
+            @file.property(:source).retrieve
+            lambda { @file.property(:source).sync }.should raise_error(Puppet::Error)
+        end
+    end
+
+    describe "when managing links" do
+        require 'puppettest/support/assertions'
+        include PuppetTest
+        require 'tempfile'
+
+        before do
+            @basedir = tempfile
+            Dir.mkdir(@basedir)
+            @file = File.join(@basedir, "file")
+            @link = File.join(@basedir, "link")
+
+            File.open(@file, "w", 0644) { |f| f.puts "yayness"; f.flush }
+            File.symlink(@file, @link)
+
+            @resource = Puppet.type(:file).create(
+                :path => @link,
+                :mode => "755"
+            )
+            @catalog = Puppet::Node::Catalog.new
+            @catalog.add_resource @resource
+        end
+
+        after do
+            remove_tmp_files
+        end
+
+        it "should default to managing the link" do
+            @catalog.apply
+            # I convert them to strings so they display correctly if there's an error.
+            ("%o" % (File.stat(@file).mode & 007777)).should == "%o" % 0644
+        end
+
+        it "should be able to follow links" do
+            @resource[:links] = :follow
+            @catalog.apply
+
+            ("%o" % (File.stat(@file).mode & 007777)).should == "%o" % 0755
+        end
+    end
+
+    after do
+        Puppet::Type::File.clear
+    end
+end
diff --git a/spec/unit/ral/type/interface.rb b/spec/unit/ral/type/interface.rb
new file mode 100755
index 0000000..2e01761
--- /dev/null
+++ b/spec/unit/ral/type/interface.rb
@@ -0,0 +1,95 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+interface = Puppet::Type.type(:interface)
+
+describe interface do
+    before do
+        @class = Puppet::Type.type(:interface)
+
+        @provider_class = stub 'provider_class', :name => "fake", :suitable? => true, :supports_parameter? => true
+        @class.stubs(:defaultprovider).returns(@provider_class)
+        @class.stubs(:provider).returns(@provider_class)
+
+        @provider = stub 'provider', :class => @provider_class, :file_path => "/tmp/whatever", :clear => nil
+        @provider_class.stubs(:new).returns(@provider)
+    end
+
+    it "should have a name parameter" do
+        @class.attrtype(:name).should == :param
+    end
+
+    it "should have :name be its namevar" do
+        @class.namevar.should == :name
+    end
+
+    it "should have a :provider parameter" do
+        @class.attrtype(:provider).should == :param
+    end
+
+    it "should have an ensure property" do
+        @class.attrtype(:ensure).should == :property
+    end
+
+    it "should support :present as a value for :ensure" do
+        proc { @class.create(:name => "whev", :ensure => :present) }.should_not raise_error
+    end
+
+    it "should support :absent as a value for :ensure" do
+        proc { @class.create(:name => "whev", :ensure => :absent) }.should_not raise_error
+    end
+
+    it "should have an interface_type property" do
+        @class.attrtype(:interface_type).should == :property
+    end
+    it "should support :loopback as an interface_type value" do
+        proc { @class.create(:name => "whev", :interface_type => :loopback) }.should_not raise_error
+    end
+    it "should support :alias as an interface_type value" do
+        proc { @class.create(:name => "whev", :interface_type => :alias) }.should_not raise_error
+    end
+    it "should support :normal as an interface_type value" do
+        proc { @class.create(:name => "whev", :interface_type => :normal) }.should_not raise_error
+    end
+    it "should alias :dummy to the :loopback interface_type value" do
+        int = @class.create(:name => "whev", :interface_type => :dummy)
+        int.should(:interface_type).should == :loopback
+    end
+
+    it "should not support values other than :loopback, :alias, :normal, and :dummy in the interface_type" do
+        proc { @class.create(:name => "whev", :interface_type => :something) }.should raise_error(Puppet::Error)
+    end
+
+    it "should have an interface_desc parameter" do
+        @class.attrtype(:interface_desc).should == :param
+    end
+
+    it "should have an onboot property" do
+        @class.attrtype(:onboot).should == :property
+    end
+    it "should support :true as an onboot value" do
+        proc { @class.create(:name => "whev", :onboot => :true) }.should_not raise_error
+    end
+    it "should support :false as an onboot value" do
+        proc { @class.create(:name => "whev", :onboot => :false) }.should_not raise_error
+    end
+
+    it "should have an ifnum property" do
+        @class.attrtype(:ifnum).should == :property
+    end
+
+    it "should have a netmask property" do
+        @class.attrtype(:netmask).should == :property
+    end
+
+    it "should have an ifopts property" do
+        @class.attrtype(:ifopts).should == :property
+    end
+
+    it "should have a target parameter" do
+        @class.attrtype(:target).should == :param
+    end
+
+    after { @class.clear }
+end
diff --git a/spec/unit/ral/type/mount.rb b/spec/unit/ral/type/mount.rb
new file mode 100755
index 0000000..8fa2e6f
--- /dev/null
+++ b/spec/unit/ral/type/mount.rb
@@ -0,0 +1,192 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/type/mount'
+
+describe Puppet::Type::Mount do
+    it "should have a :refreshable feature that requires the :remount method" do
+        Puppet::Type::Mount.provider_feature(:refreshable).methods.should == [:remount]
+    end
+
+    it "should have no default value for :ensure" do
+        mount = Puppet::Type::Mount.create(:name => "yay")
+        mount.should(:ensure).should be_nil
+    end
+
+    after { Puppet::Type::Mount.clear }
+end
+
+describe Puppet::Type::Mount, "when validating attributes" do
+    [:name, :remounts].each do |param|
+        it "should have a #{param} parameter" do
+            Puppet::Type::Mount.attrtype(param).should == :param
+        end
+    end
+
+    [:ensure, :device, :blockdevice, :fstype, :options, :pass, :dump, :atboot, :target].each do |param|
+        it "should have a #{param} property" do
+            Puppet::Type::Mount.attrtype(param).should == :property
+        end
+    end
+end
+
+describe Puppet::Type::Mount::Ensure, "when validating values" do
+    before do
+        @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil
+        Puppet::Type::Mount.defaultprovider.expects(:new).returns(@provider)
+    end
+
+    it "should support :present as a value to :ensure" do
+        Puppet::Type::Mount.create(:name => "yay", :ensure => :present)
+    end
+
+    it "should alias :unmounted to :present as a value to :ensure" do
+        mount = Puppet::Type::Mount.create(:name => "yay", :ensure => :unmounted)
+        mount.should(:ensure).should == :present
+    end
+
+    it "should support :absent as a value to :ensure" do
+        Puppet::Type::Mount.create(:name => "yay", :ensure => :absent)
+    end
+
+    it "should support :mounted as a value to :ensure" do
+        Puppet::Type::Mount.create(:name => "yay", :ensure => :mounted)
+    end
+
+    after { Puppet::Type::Mount.clear }
+end
+
+describe Puppet::Type::Mount::Ensure do
+    before :each do
+        @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock
+        Puppet::Type::Mount.defaultprovider.stubs(:new).returns(@provider)
+        @mount = Puppet::Type::Mount.create(:name => "yay", :check => :ensure)
+
+        @ensure = @mount.property(:ensure)
+    end
+
+    after :each do
+        Puppet::Type::Mount.clear
+    end
+    
+    def mount_stub(params)
+        Puppet::Type::Mount.validproperties.each do |prop|
+            unless params[prop]
+                params[prop] = :absent
+                @mount[prop] = :absent
+            end
+        end
+
+        params.each do |param, value|
+            @provider.stubs(param).returns(value)
+        end
+    end
+
+    describe Puppet::Type::Mount::Ensure, "when retrieving its current state" do
+
+        it "should return the provider's value if it is :absent" do
+            @provider.expects(:ensure).returns(:absent)
+            @ensure.retrieve.should == :absent
+        end
+
+        it "should return :mounted if the provider indicates it is mounted and the value is not :absent" do
+            @provider.expects(:ensure).returns(:present)
+            @provider.expects(:mounted?).returns(true)
+            @ensure.retrieve.should == :mounted
+        end
+
+        it "should return :present if the provider indicates it is not mounted and the value is not :absent" do
+            @provider.expects(:ensure).returns(:present)
+            @provider.expects(:mounted?).returns(false)
+            @ensure.retrieve.should == :present
+        end
+    end
+
+    describe Puppet::Type::Mount::Ensure, "when changing the host" do
+
+        it "should destroy itself if it should be absent" do
+            @provider.stubs(:mounted?).returns(false)
+            @provider.expects(:destroy)
+            @ensure.should = :absent
+            @ensure.sync
+        end
+
+        it "should unmount itself before destroying if it is mounted and should be absent" do
+            @provider.expects(:mounted?).returns(true)
+            @provider.expects(:unmount)
+            @provider.expects(:destroy)
+            @ensure.should = :absent
+            @ensure.sync
+        end
+
+        it "should create itself if it is absent and should be present" do
+            @provider.stubs(:mounted?).returns(false)
+            @provider.expects(:create)
+            @ensure.should = :present
+            @ensure.sync
+        end
+
+        it "should unmount itself if it is mounted and should be present" do
+            @provider.stubs(:mounted?).returns(true)
+
+            # The interface here is just too much work to test right now.
+            @ensure.stubs(:syncothers)
+            @provider.expects(:unmount)
+            @ensure.should = :present
+            @ensure.sync
+        end
+
+        it "should create and mount itself if it does not exist and should be mounted" do
+            @provider.stubs(:ensure).returns(:absent)
+            @provider.stubs(:mounted?).returns(false)
+            @provider.expects(:create)
+            @ensure.stubs(:syncothers)
+            @provider.expects(:mount)
+            @ensure.should = :mounted
+            @ensure.sync
+        end
+
+        it "should mount itself if it is present and should be mounted" do
+            @provider.stubs(:ensure).returns(:present)
+            @provider.stubs(:mounted?).returns(false)
+            @ensure.stubs(:syncothers)
+            @provider.expects(:mount)
+            @ensure.should = :mounted
+            @ensure.sync
+        end
+
+        it "should create but not mount itself if it is absent and mounted and should be mounted" do
+            @provider.stubs(:ensure).returns(:absent)
+            @provider.stubs(:mounted?).returns(true)
+            @ensure.stubs(:syncothers)
+            @provider.expects(:create)
+            @ensure.should = :mounted
+            @ensure.sync
+        end
+    end
+
+    describe Puppet::Type::Mount, "when responding to events" do
+
+        it "should remount if it is currently mounted" do
+            @provider.expects(:mounted?).returns(true)
+            @provider.expects(:remount)
+
+            @mount.refresh
+        end
+
+        it "should not remount if it is not currently mounted" do
+            @provider.expects(:mounted?).returns(false)
+            @provider.expects(:remount).never
+
+            @mount.refresh
+        end
+
+        it "should not remount swap filesystems" do
+            @mount[:fstype] = "swap"
+            @provider.expects(:remount).never
+
+            @mount.refresh
+        end
+    end
+end
diff --git a/spec/unit/ral/type/nagios.rb b/spec/unit/ral/type/nagios.rb
new file mode 100755
index 0000000..35f00b0
--- /dev/null
+++ b/spec/unit/ral/type/nagios.rb
@@ -0,0 +1,63 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/external/nagios'
+
+describe "Nagios resource types" do
+    Nagios::Base.eachtype do |name, nagios_type|
+        puppet_type = Puppet::Type.type("nagios_" + name.to_s)
+
+        it "should have a valid type for #{name}" do
+            puppet_type.should_not be_nil
+        end
+
+        next unless puppet_type
+
+        describe puppet_type do
+            it "should be defined as a Puppet resource type" do
+                puppet_type.should_not be_nil
+            end
+
+            it "should have documentation" do
+                puppet_type.instance_variable_get("@doc").should_not == ""
+            end
+
+            it "should have %s as its namevar" % nagios_type.namevar do
+                puppet_type.namevar.should == nagios_type.namevar
+            end
+
+            it "should have documentation for its %s parameter" % nagios_type.namevar do
+                puppet_type.attrclass(nagios_type.namevar).instance_variable_get("@doc").should_not be_nil
+            end
+
+            it "should have an ensure property" do
+                puppet_type.should be_validproperty(:ensure)
+            end
+
+            it "should have a target property" do
+                puppet_type.should be_validproperty(:target)
+            end
+
+            it "should have documentation for its target property" do
+                puppet_type.attrclass(:target).instance_variable_get("@doc").should_not be_nil
+            end
+
+            nagios_type.parameters.reject { |param| param == nagios_type.namevar or param.to_s =~ /^[0-9]/ }.each do |param|
+                it "should have a %s property" % param do
+                    puppet_type.should be_validproperty(param)
+                end
+
+                it "should have documentation for its %s property" % param do
+                    puppet_type.attrclass(param).instance_variable_get("@doc").should_not be_nil
+                end
+            end
+
+            nagios_type.parameters.find_all { |param| param.to_s =~ /^[0-9]/ }.each do |param|
+                it "should have not have a %s property" % param do
+                    puppet_type.should_not be_validproperty(:param)
+                end
+            end
+        end
+    end
+end
diff --git a/spec/unit/ral/type/noop_metaparam.rb b/spec/unit/ral/type/noop_metaparam.rb
new file mode 100755
index 0000000..0cbed37
--- /dev/null
+++ b/spec/unit/ral/type/noop_metaparam.rb
@@ -0,0 +1,38 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/metatype/metaparams'
+
+describe Puppet::Type.type(:file).attrclass(:noop) do
+    before do
+        @file = Puppet::Type.newfile :path => "/what/ever"
+    end
+
+    after { Puppet::Type::File.clear }
+
+    it "should accept true as a value" do
+        lambda { @file[:noop] = true }.should_not raise_error
+    end
+
+    it "should accept false as a value" do
+        lambda { @file[:noop] = false }.should_not raise_error
+    end
+
+    describe "when set on a resource" do
+        it "should default to the :noop setting" do
+            Puppet.settings.expects(:value).with(:noop).returns "myval"
+            @file.noop.should == "myval"
+        end
+
+        it "should prefer true values from the attribute" do
+            @file[:noop] = true
+            @file.noop.should be_true
+        end
+
+        it "should prefer false values from the attribute" do
+            @file[:noop] = false
+            @file.noop.should be_false
+        end
+    end
+end
diff --git a/spec/unit/ral/type/package.rb b/spec/unit/ral/type/package.rb
new file mode 100755
index 0000000..5d96dc4
--- /dev/null
+++ b/spec/unit/ral/type/package.rb
@@ -0,0 +1,247 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/type/package'
+
+describe Puppet::Type::Package do
+    it "should have an :installable feature that requires the :install method" do
+        Puppet::Type::Package.provider_feature(:installable).methods.should == [:install]
+    end
+
+    it "should have an :uninstallable feature that requires the :uninstall method" do
+        Puppet::Type::Package.provider_feature(:uninstallable).methods.should == [:uninstall]
+    end
+
+    it "should have an :upgradeable feature that requires :update and :latest methods" do
+        Puppet::Type::Package.provider_feature(:upgradeable).methods.should == [:update, :latest]
+    end
+
+    it "should have a :purgeable feature that requires the :purge latest method" do
+        Puppet::Type::Package.provider_feature(:purgeable).methods.should == [:purge]
+    end
+
+    it "should have a :versionable feature" do
+        Puppet::Type::Package.provider_feature(:versionable).should_not be_nil
+    end
+
+    it "should default to being installed" do
+        pkg = Puppet::Type::Package.create(:name => "yay")
+        pkg.should(:ensure).should == :present
+    end
+
+    after { Puppet::Type::Package.clear }
+end
+
+describe Puppet::Type::Package, "when validating attributes" do
+    [:name, :source, :instance, :status, :adminfile, :responsefile, :configfiles, :category, :platform, :root, :vendor, :description, :allowcdrom].each do |param|
+        it "should have a #{param} parameter" do
+            Puppet::Type::Package.attrtype(param).should == :param
+        end
+    end
+
+    it "should have an ensure property" do
+        Puppet::Type::Package.attrtype(:ensure).should == :property
+    end
+end
+
+describe Puppet::Type::Package, "when validating attribute values" do
+    before do
+        @provider = stub 'provider', :class => Puppet::Type::Package.defaultprovider, :clear => nil
+        Puppet::Type::Package.defaultprovider.expects(:new).returns(@provider)
+    end
+
+    it "should support :present as a value to :ensure" do
+        Puppet::Type::Package.create(:name => "yay", :ensure => :present)
+    end
+
+    it "should alias :installed to :present as a value to :ensure" do
+        pkg = Puppet::Type::Package.create(:name => "yay", :ensure => :installed)
+        pkg.should(:ensure).should == :present
+    end
+
+    it "should support :absent as a value to :ensure" do
+        Puppet::Type::Package.create(:name => "yay", :ensure => :absent)
+    end
+
+    it "should support :purged as a value to :ensure if the provider has the :purgeable feature" do
+        @provider.expects(:satisfies?).with(:purgeable).returns(true)
+        Puppet::Type::Package.create(:name => "yay", :ensure => :purged)
+    end
+
+    it "should not support :purged as a value to :ensure if the provider does not have the :purgeable feature" do
+        @provider.expects(:satisfies?).with(:purgeable).returns(false)
+        proc { Puppet::Type::Package.create(:name => "yay", :ensure => :purged) }.should raise_error(Puppet::Error)
+    end
+
+    it "should support :latest as a value to :ensure if the provider has the :upgradeable feature" do
+        @provider.expects(:satisfies?).with(:upgradeable).returns(true)
+        Puppet::Type::Package.create(:name => "yay", :ensure => :latest)
+    end
+
+    it "should not support :latest as a value to :ensure if the provider does not have the :upgradeable feature" do
+        @provider.expects(:satisfies?).with(:upgradeable).returns(false)
+        proc { Puppet::Type::Package.create(:name => "yay", :ensure => :latest) }.should raise_error(Puppet::Error)
+    end
+
+    it "should support version numbers as a value to :ensure if the provider has the :versionable feature" do
+        @provider.expects(:satisfies?).with(:versionable).returns(true)
+        Puppet::Type::Package.create(:name => "yay", :ensure => "1.0")
+    end
+
+    it "should not support version numbers as a value to :ensure if the provider does not have the :versionable feature" do
+        @provider.expects(:satisfies?).with(:versionable).returns(false)
+        proc { Puppet::Type::Package.create(:name => "yay", :ensure => "1.0") }.should raise_error(Puppet::Error)
+    end
+
+    it "should accept any string as an argument to :source" do
+        proc { Puppet::Type::Package.create(:name => "yay", :source => "stuff") }.should_not raise_error(Puppet::Error)
+    end
+
+    after { Puppet::Type::Package.clear }
+end
+
+module PackageEvaluationTesting
+    def setprops(properties)
+        @provider.stubs(:properties).returns(properties)
+    end
+end
+
+describe Puppet::Type::Package do
+    before :each do
+        @provider = stub 'provider', :class => Puppet::Type::Package.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock
+        Puppet::Type::Package.defaultprovider.stubs(:new).returns(@provider)
+        @package = Puppet::Type::Package.create(:name => "yay")
+
+        @catalog = Puppet::Node::Catalog.new
+        @catalog.add_resource(@package)
+    end
+    
+    after :each do
+        @catalog.clear(true)
+        Puppet::Type::Package.clear
+    end
+
+
+    describe Puppet::Type::Package, "when it should be purged" do
+        include PackageEvaluationTesting
+
+        before { @package[:ensure] = :purged }
+
+        it "should do nothing if it is :purged" do
+            @provider.expects(:properties).returns(:ensure => :purged)
+            @catalog.apply
+        end
+
+        [:absent, :installed, :present, :latest].each do |state|
+            it "should purge if it is #{state.to_s}" do
+                @provider.stubs(:properties).returns(:ensure => state)
+                @provider.expects(:purge)
+                @catalog.apply
+            end
+        end
+    end
+
+    describe Puppet::Type::Package, "when it should be absent" do
+        include PackageEvaluationTesting
+
+        before { @package[:ensure] = :absent }
+
+        [:purged, :absent].each do |state|
+            it "should do nothing if it is #{state.to_s}" do
+                @provider.expects(:properties).returns(:ensure => state)
+                @catalog.apply
+            end
+        end
+
+        [:installed, :present, :latest].each do |state|
+            it "should uninstall if it is #{state.to_s}" do
+                @provider.stubs(:properties).returns(:ensure => state)
+                @provider.expects(:uninstall)
+                @catalog.apply
+            end
+        end
+    end
+
+    describe Puppet::Type::Package, "when it should be present" do
+        include PackageEvaluationTesting
+
+        before { @package[:ensure] = :present }
+
+        [:present, :latest, "1.0"].each do |state|
+            it "should do nothing if it is #{state.to_s}" do
+                @provider.expects(:properties).returns(:ensure => state)
+                @catalog.apply
+            end
+        end
+
+        [:purged, :absent].each do |state|
+            it "should install if it is #{state.to_s}" do
+                @provider.stubs(:properties).returns(:ensure => state)
+                @provider.expects(:install)
+                @catalog.apply
+            end
+        end
+    end
+
+    describe Puppet::Type::Package, "when it should be latest" do
+        include PackageEvaluationTesting
+
+        before { @package[:ensure] = :latest }
+
+        [:purged, :absent].each do |state|
+            it "should upgrade if it is #{state.to_s}" do
+                @provider.stubs(:properties).returns(:ensure => state)
+                @provider.expects(:update)
+                @catalog.apply
+            end
+        end
+
+        it "should upgrade if the current version is not equal to the latest version" do
+            @provider.stubs(:properties).returns(:ensure => "1.0")
+            @provider.stubs(:latest).returns("2.0")
+            @provider.expects(:update)
+            @catalog.apply
+        end
+
+        it "should do nothing if it is equal to the latest version" do
+            @provider.stubs(:properties).returns(:ensure => "1.0")
+            @provider.stubs(:latest).returns("1.0")
+            @provider.expects(:update).never
+            @catalog.apply
+        end
+
+        it "should do nothing if the provider returns :present as the latest version" do
+            @provider.stubs(:properties).returns(:ensure => :present)
+            @provider.stubs(:latest).returns("1.0")
+            @provider.expects(:update).never
+            @catalog.apply
+        end
+    end
+
+    describe Puppet::Type::Package, "when it should be a specific version" do
+        include PackageEvaluationTesting
+
+        before { @package[:ensure] = "1.0" }
+
+        [:purged, :absent].each do |state|
+            it "should install if it is #{state.to_s}" do
+                @provider.stubs(:properties).returns(:ensure => state)
+                @provider.expects(:install)
+                @catalog.apply
+            end
+        end
+
+        it "should do nothing if the current version is equal to the desired version" do
+            @provider.stubs(:properties).returns(:ensure => "1.0")
+            @provider.expects(:install).never
+            @catalog.apply
+        end
+
+        it "should install if the current version is not equal to the specified version" do
+            @provider.stubs(:properties).returns(:ensure => "2.0")
+            @provider.expects(:install)
+            @catalog.apply
+        end
+    end
+end
diff --git a/spec/unit/ral/type/schedule.rb b/spec/unit/ral/type/schedule.rb
new file mode 100755
index 0000000..4e9840c
--- /dev/null
+++ b/spec/unit/ral/type/schedule.rb
@@ -0,0 +1,341 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/type/schedule'
+
+module ScheduleTesting
+
+    def format(time)
+        time.strftime("%H:%M:%S")
+    end
+
+    def diff(unit, incr, method, count)
+        diff = Time.now.to_i.send(method, incr * count)
+        Time.at(diff)
+    end
+
+    def month(method, count)
+        diff(:hour, 3600 * 24 * 30, method, count)
+    end
+
+    def week(method, count)
+        diff(:hour, 3600 * 24 * 7, method, count)
+    end
+
+    def day(method, count)
+        diff(:hour, 3600 * 24, method, count)
+    end
+
+    def hour(method, count)
+        diff(:hour, 3600, method, count)
+    end
+
+    def min(method, count)
+        diff(:min, 60, method, count)
+    end
+
+    def sec(method, count)
+        diff(:sec, 1, method, count)
+    end
+
+end
+
+describe Puppet::Type::Schedule do
+
+    before :each do
+      Puppet.settings.stubs(:value).with(:ignoreschedules).returns(false)
+
+      @schedule = Puppet::Type::Schedule.create(:name => "testing")
+    end
+
+    after :each do
+        Puppet::Type::Schedule.clear
+    end
+
+
+    describe Puppet::Type::Schedule do
+        include ScheduleTesting
+
+        it "should default to :distance for period-matching" do
+            @schedule[:periodmatch].should == :distance
+        end
+
+        it "should default to a :repeat of 1" do
+            @schedule[:repeat].should == 1
+        end
+
+        it "should never match when the period is :never" do
+            @schedule[:period] = :never
+            @schedule.match?.should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when producing default schedules" do
+        include ScheduleTesting
+
+        %w{hourly daily weekly monthly never}.each do |period|
+            period = period.to_sym
+            it "should produce a #{period} schedule with the period set appropriately" do
+                schedules = Puppet::Type::Schedule.mkdefaultschedules
+                schedules.find { |s| s[:name] == period.to_s and s[:period] == period }.should be_instance_of(Puppet::Type::Schedule)
+            end
+        end
+
+        it "should produce a schedule named puppet with a period of hourly and a repeat of 2" do
+            schedules = Puppet::Type::Schedule.mkdefaultschedules
+            schedules.find { |s|
+                s[:name] == "puppet" and s[:period] == :hourly and s[:repeat] == 2
+            }.should be_instance_of(Puppet::Type::Schedule)
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching ranges" do
+        include ScheduleTesting
+
+        it "should match when the start time is before the current time and the end time is after the current time" do
+            @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now + 10)]
+            @schedule.match?.should be_true
+        end
+
+        it "should not match when the start time is after the current time" do
+            @schedule[:range] = "%s - %s" % [format(Time.now + 5), format(Time.now + 10)]
+            @schedule.match?.should be_false
+        end
+
+        it "should not match when the end time is previous to the current time" do
+            @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now - 5)]
+            @schedule.match?.should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching hourly by distance" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :hourly
+            @schedule[:periodmatch] = :distance
+        end
+
+        it "should match an hour ago" do
+            @schedule.match?(hour("-", 1)).should be_true
+        end
+
+        it "should not match now" do
+            @schedule.match?(Time.now).should be_false
+        end
+
+        it "should not match 59 minutes ago" do
+            @schedule.match?(min("-", 59)).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching daily by distance" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :daily
+            @schedule[:periodmatch] = :distance
+        end
+
+        it "should match when the previous time was one day ago" do
+            @schedule.match?(day("-", 1)).should be_true
+        end
+
+        it "should not match when the previous time is now" do
+            @schedule.match?(Time.now).should be_false
+        end
+
+        it "should not match when the previous time was 23 hours ago" do
+            @schedule.match?(hour("-", 23)).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching weekly by distance" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :weekly
+            @schedule[:periodmatch] = :distance
+        end
+
+        it "should match seven days ago" do
+            @schedule.match?(day("-", 7)).should be_true
+        end
+
+        it "should not match now" do
+            @schedule.match?(Time.now).should be_false
+        end
+
+        it "should not match six days ago" do
+            @schedule.match?(day("-", 6)).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching monthly by distance" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :monthly
+            @schedule[:periodmatch] = :distance
+        end
+
+        it "should match 32 days ago" do
+            @schedule.match?(day("-", 32)).should be_true
+        end
+
+        it "should not match now" do
+            @schedule.match?(Time.now).should be_false
+        end
+
+        it "should not match 27 days ago" do
+            @schedule.match?(day("-", 27)).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching hourly by number" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :hourly
+            @schedule[:periodmatch] = :number
+        end
+
+        it "should match if the times are one minute apart and the current minute is 0" do
+            current = Time.now
+
+            # Subtract an hour, reset the minute to zero, then add 59 minutes, so we're the previous hour plus 59 minutes.
+            previous = (current - 3600 - (current.min * 60) + (59 * 60))
+
+            # Now set the "current" time to the zero minute of the current hour.
+            now = (current - (current.min * 60))
+            Time.stubs(:now).returns(now)
+            @schedule.match?(previous).should be_true
+        end
+
+        it "should not match if the times are 58 minutes apart and the current minute is 59" do
+            current = Time.now
+
+            # reset the minute to zero
+            previous = current - (current.min * 60)
+
+            # Now set the "current" time to the 59th minute of the current hour.
+            now = (current - (current.min * 60) + (59 * 60))
+            Time.stubs(:now).returns(now)
+            @schedule.match?(previous).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching daily by number" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :daily
+            @schedule[:periodmatch] = :number
+        end
+
+        it "should match if the times are one minute apart and the current minute and hour are 0" do
+            zero = Time.now
+
+            # Reset the current time to X:00:00
+            current = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec
+
+            # Now set the previous time to one minute before that
+            previous = current - 60
+
+            Time.stubs(:now).returns(current)
+            @schedule.match?(previous).should be_true
+        end
+
+        it "should not match if the times are 23 hours and 58 minutes apart and the current hour is 23 and the current minute is 59" do
+            zero = Time.now
+
+            # Reset the previous time to 00:00:00
+            previous = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec
+
+            # Set the current time to 23:59
+            now = previous + (23 * 3600) + (59 * 60)
+
+            Time.stubs(:now).returns(now)
+            @schedule.match?(previous).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching weekly by number" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :weekly
+            @schedule[:periodmatch] = :number
+        end
+
+        it "should match if the previous time is prior to the most recent Sunday" do
+            now = Time.now
+
+            # Subtract the number days we've progressed into the week, plus one because we're zero-indexed.
+            previous = now - (3600 * 24 * (now.wday + 1))
+
+            @schedule.match?(previous).should be_true
+        end
+
+        it "should not match if the previous time is after the most recent Saturday" do
+            now = Time.now
+
+            # Subtract the number days we've progressed into the week
+            previous = now - (3600 * 24 * now.wday)
+
+            @schedule.match?(previous).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching monthly by number" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :monthly
+            @schedule[:periodmatch] = :number
+        end
+
+        it "should match when the previous time is prior to the first day of this month" do
+            now = Time.now
+
+            # Subtract the number days we've progressed into the month
+            previous = now - (3600 * 24 * now.day)
+
+            @schedule.match?(previous).should be_true
+        end
+
+        it "should not match when the previous time is after the last day of last month" do
+            now = Time.now
+
+            # Subtract the number days we've progressed into the month, minus one
+            previous = now - (3600 * 24 * (now.day - 1))
+
+            @schedule.match?(previous).should be_false
+        end
+    end
+
+    describe Puppet::Type::Schedule, "when matching with a repeat greater than one" do
+        include ScheduleTesting
+
+        before do
+            @schedule[:period] = :daily
+            @schedule[:repeat] = 2
+        end
+
+        it "should fail if the periodmatch is 'number'" do
+            @schedule[:periodmatch] = :number
+            proc { @schedule[:repeat] = 2 }.should raise_error(Puppet::Error)
+        end
+
+        it "should match if the previous run was further away than the distance divided by the repeat" do
+            previous = Time.now - (3600 * 13)
+            @schedule.match?(previous).should be_true
+        end
+
+        it "should not match if the previous run was closer than the distance divided by the repeat" do
+            previous = Time.now - (3600 * 11)
+            @schedule.match?(previous).should be_false
+        end
+    end
+end
diff --git a/spec/unit/ral/type/service.rb b/spec/unit/ral/type/service.rb
new file mode 100755
index 0000000..0f00992
--- /dev/null
+++ b/spec/unit/ral/type/service.rb
@@ -0,0 +1,256 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/type/service'
+
+describe Puppet::Type::Service do
+    it "should have an :enableable feature that requires the :enable, :disable, and :enabled? methods" do
+        Puppet::Type::Service.provider_feature(:enableable).methods.should == [:disable, :enable, :enabled?]
+    end
+
+    it "should have a :refreshable feature that requires the :restart method" do
+        Puppet::Type::Service.provider_feature(:refreshable).methods.should == [:restart]
+    end
+end
+
+describe Puppet::Type::Service, "when validating attributes" do
+    [:name, :binary, :hasstatus, :path, :pattern, :start, :restart, :stop, :status, :hasrestart, :control].each do |param|
+        it "should have a #{param} parameter" do
+            Puppet::Type::Service.attrtype(param).should == :param
+        end
+    end
+
+    [:ensure, :enable].each do |param|
+        it "should have an #{param} property" do
+            Puppet::Type::Service.attrtype(param).should == :property
+        end
+    end
+end
+
+describe Puppet::Type::Service, "when validating attribute values" do
+    before do
+        @provider = stub 'provider', :class => Puppet::Type::Service.defaultprovider, :clear => nil, :controllable? => false
+        Puppet::Type::Service.defaultprovider.stubs(:new).returns(@provider)
+    end
+
+    it "should support :running as a value to :ensure" do
+        Puppet::Type::Service.create(:name => "yay", :ensure => :running)
+    end
+
+    it "should support :stopped as a value to :ensure" do
+        Puppet::Type::Service.create(:name => "yay", :ensure => :stopped)
+    end
+
+    it "should alias the value :true to :running in :ensure" do
+        svc = Puppet::Type::Service.create(:name => "yay", :ensure => true)
+        svc.should(:ensure).should == :running
+    end
+
+    it "should alias the value :false to :stopped in :ensure" do
+        svc = Puppet::Type::Service.create(:name => "yay", :ensure => false)
+        svc.should(:ensure).should == :stopped
+    end
+
+    it "should support :true as a value to :enable" do
+        Puppet::Type::Service.create(:name => "yay", :enable => :true)
+    end
+
+    it "should support :false as a value to :enable" do
+        Puppet::Type::Service.create(:name => "yay", :enable => :false)
+    end
+
+    it "should support :true as a value to :hasstatus" do
+        Puppet::Type::Service.create(:name => "yay", :hasstatus => :true)
+    end
+
+    it "should support :false as a value to :hasstatus" do
+        Puppet::Type::Service.create(:name => "yay", :hasstatus => :false)
+    end
+
+    it "should support :true as a value to :hasrestart" do
+        Puppet::Type::Service.create(:name => "yay", :hasrestart => :true)
+    end
+
+    it "should support :false as a value to :hasrestart" do
+        Puppet::Type::Service.create(:name => "yay", :hasrestart => :false)
+    end
+
+    it "should allow setting the :enable parameter if the provider has the :enableable feature" do
+        Puppet::Type::Service.defaultprovider.stubs(:supports_parameter?).returns(true)
+        Puppet::Type::Service.defaultprovider.expects(:supports_parameter?).with(Puppet::Type::Service.attrclass(:enable)).returns(true)
+        svc = Puppet::Type::Service.create(:name => "yay", :enable => true)
+        svc.should(:enable).should == :true
+    end
+
+    it "should not allow setting the :enable parameter if the provider is missing the :enableable feature" do
+        Puppet::Type::Service.defaultprovider.stubs(:supports_parameter?).returns(true)
+        Puppet::Type::Service.defaultprovider.expects(:supports_parameter?).with(Puppet::Type::Service.attrclass(:enable)).returns(false)
+        svc = Puppet::Type::Service.create(:name => "yay", :enable => true)
+        svc.should(:enable).should be_nil
+    end
+
+    it "should discard paths that do not exist" do
+        FileTest.stubs(:exist?).returns(false)
+        FileTest.stubs(:directory?).returns(false)
+        svc = Puppet::Type::Service.create(:name => "yay", :path => "/one/two")
+        svc[:path].should be_empty
+    end
+
+    it "should discard paths that are not directories" do
+        FileTest.stubs(:exist?).returns(true)
+        FileTest.stubs(:directory?).returns(false)
+        svc = Puppet::Type::Service.create(:name => "yay", :path => "/one/two")
+        svc[:path].should be_empty
+    end
+
+    it "should split paths on ':'" do
+        FileTest.stubs(:exist?).returns(true)
+        FileTest.stubs(:directory?).returns(true)
+        svc = Puppet::Type::Service.create(:name => "yay", :path => "/one/two:/three/four")
+        svc[:path].should == %w{/one/two /three/four}
+    end
+
+    it "should accept arrays of paths joined by ':'" do
+        FileTest.stubs(:exist?).returns(true)
+        FileTest.stubs(:directory?).returns(true)
+        svc = Puppet::Type::Service.create(:name => "yay", :path => ["/one:/two", "/three:/four"])
+        svc[:path].should == %w{/one /two /three /four}
+    end
+
+    after { Puppet::Type::Service.clear }
+end
+
+describe Puppet::Type::Service, "when setting default attribute values" do
+    it "should default to the provider's default path if one is available" do
+        FileTest.stubs(:directory?).returns(true)
+        FileTest.stubs(:exist?).returns(true)
+
+        Puppet::Type::Service.defaultprovider.stubs(:respond_to?).returns(true)
+        Puppet::Type::Service.defaultprovider.stubs(:defpath).returns("testing")
+        svc = Puppet::Type::Service.create(:name => "other")
+        svc[:path].should == ["testing"]
+    end
+
+    it "should default 'pattern' to the binary if one is provided" do
+        svc = Puppet::Type::Service.create(:name => "other", :binary => "/some/binary")
+        svc[:pattern].should == "/some/binary"
+    end
+
+    it "should default 'pattern' to the name if no pattern is provided" do
+        svc = Puppet::Type::Service.create(:name => "other")
+        svc[:pattern].should == "other"
+    end
+
+    it "should default 'control' to the upcased service name with periods replaced by underscores if the provider supports the 'controllable' feature" do
+        provider = stub 'provider', :controllable? => true, :class => Puppet::Type::Service.defaultprovider, :clear => nil
+        Puppet::Type::Service.defaultprovider.stubs(:new).returns(provider)
+        svc = Puppet::Type::Service.create(:name => "nfs.client")
+        svc[:control].should == "NFS_CLIENT_START"
+    end
+
+    after { Puppet::Type::Service.clear }
+end
+
+describe Puppet::Type::Service, "when retrieving the host's current state" do
+    before do
+        @service = Puppet::Type::Service.create(:name => "yay")
+    end
+
+    it "should use the provider's status to determine whether the service is running" do
+        @service.provider.expects(:status).returns(:yepper)
+        @service[:ensure] = :running
+        @service.property(:ensure).retrieve.should == :yepper
+    end
+
+    it "should ask the provider whether it is enabled" do
+        @service.provider.class.stubs(:supports_parameter?).returns(true)
+        @service.provider.expects(:enabled?).returns(:yepper)
+        @service[:enable] = true
+        @service.property(:enable).retrieve.should == :yepper
+    end
+
+    after { Puppet::Type::Service.clear }
+end
+
+describe Puppet::Type::Service, "when changing the host" do
+    before do
+        @service = Puppet::Type::Service.create(:name => "yay")
+    end
+
+    it "should start the service if it is supposed to be running" do
+        @service[:ensure] = :running
+        @service.provider.expects(:start)
+        @service.property(:ensure).sync
+    end
+
+    it "should stop the service if it is supposed to be stopped" do
+        @service[:ensure] = :stopped
+        @service.provider.expects(:stop)
+        @service.property(:ensure).sync
+    end
+
+    it "should enable the service if it is supposed to be enabled" do
+        @service.provider.class.stubs(:supports_parameter?).returns(true)
+        @service[:enable] = true
+        @service.provider.expects(:enable)
+        @service.property(:enable).sync
+    end
+
+    it "should disable the service if it is supposed to be disabled" do
+        @service.provider.class.stubs(:supports_parameter?).returns(true)
+        @service[:enable] = false
+        @service.provider.expects(:disable)
+        @service.property(:enable).sync
+    end
+
+    it "should sync the service's enable state when changing the state of :ensure if :enable is being managed" do
+        @service.provider.class.stubs(:supports_parameter?).returns(true)
+        @service[:enable] = false
+        @service[:ensure] = :stopped
+
+        @service.property(:enable).expects(:retrieve).returns("whatever")
+        @service.property(:enable).expects(:insync?).returns(false)
+        @service.property(:enable).expects(:sync)
+
+        @service.provider.stubs(:stop)
+
+        @service.property(:ensure).sync
+    end
+
+    after { Puppet::Type::Service.clear }
+end
+
+describe Puppet::Type::Service, "when refreshing the service" do
+    before do
+        @service = Puppet::Type::Service.create(:name => "yay")
+    end
+
+    it "should restart the service if it is running" do
+        @service[:ensure] = :running
+        @service.provider.expects(:status).returns(:running)
+        @service.provider.expects(:restart)
+        @service.refresh
+    end
+
+    it "should restart the service if it is running, even if it is supposed to stopped" do
+        @service[:ensure] = :stopped
+        @service.provider.expects(:status).returns(:running)
+        @service.provider.expects(:restart)
+        @service.refresh
+    end
+
+    it "should not restart the service if it is not running" do
+        @service[:ensure] = :running
+        @service.provider.expects(:status).returns(:stopped)
+        @service.refresh
+    end
+
+    it "should add :ensure as a property if it is not being managed" do
+        @service.provider.expects(:status).returns(:running)
+        @service.provider.expects(:restart)
+        @service.refresh
+    end
+
+    after { Puppet::Type::Service.clear }
+end
diff --git a/spec/unit/ral/type/user.rb b/spec/unit/ral/type/user.rb
new file mode 100755
index 0000000..4e43a8c
--- /dev/null
+++ b/spec/unit/ral/type/user.rb
@@ -0,0 +1,58 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/type/user'
+
+module UserTestFunctions
+    def mkuser(name)
+        user = nil;
+        lambda {
+            user = Puppet::Type::User.create(
+                :name => name,
+                :comment => "Puppet Testing User",
+                :gid => Puppet::Util::SUIDManager.gid,
+                :shell => "/bin/sh",
+                :home => "/home/%s" % name
+        ) }.should_not raise_error
+        user.should_not be_nil
+        user
+    end
+
+    def test_provider_class(klass)
+        klass.should_not be_nil
+        klass.should be_an_instance_of(Class)
+        superclasses = []
+        while klass = klass.superclass
+            superclasses << klass
+        end
+        superclasses.should include(Puppet::Provider)
+    end
+end
+
+describe Puppet::Type::User do
+
+    include UserTestFunctions
+
+    it "should have a default provider inheriting from Puppet::Provider" do
+        test_provider_class Puppet::Type::User.defaultprovider
+    end
+
+    it "should be able to create a instance" do
+        mkuser "123testuser1"
+    end
+end
+
+describe Puppet::Type::User, "instances" do
+
+    include UserTestFunctions
+
+    it "should have a valid provider" do
+        user = mkuser "123testuser2"
+        user.provider.should_not be_nil
+        test_provider_class user.provider.class
+    end
+
+end
+
+
diff --git a/spec/unit/relationship.rb b/spec/unit/relationship.rb
new file mode 100755
index 0000000..5f96cdf
--- /dev/null
+++ b/spec/unit/relationship.rb
@@ -0,0 +1,149 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-11-1.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../spec_helper'
+require 'puppet/relationship'
+
+describe Puppet::Relationship do
+    before do
+        @edge = Puppet::Relationship.new(:a, :b)
+    end
+
+    it "should have a :source attribute" do
+        @edge.should respond_to(:source)
+    end
+
+    it "should have a :target attribute" do
+        @edge.should respond_to(:target)
+    end
+
+    it "should have a :label attribute" do
+        @edge.should respond_to(:label)
+    end
+
+    it "should provide a :ref method that describes the edge" do
+        @edge = Puppet::Relationship.new("a", "b")
+        @edge.ref.should == "a => b"
+    end
+end
+
+describe Puppet::Relationship, " when initializing" do
+    before do
+        @edge = Puppet::Relationship.new(:a, :b, :testing => :foo)
+    end
+
+    it "should use the first argument as the source" do
+        @edge.source.should == :a
+    end
+
+    it "should use the second argument as the target" do
+        @edge.target.should == :b
+    end
+
+    it "should use the third argument as the label" do
+        @edge.label.should == {:testing => :foo}
+    end
+
+    it "should require a callback if a non-NONE event is specified" do
+        proc { Puppet::Relationship.new(:a, :b, :event => :something) }.should raise_error(ArgumentError)
+    end
+
+    it "should require the label to be a hash" do
+        proc { Puppet::Relationship.new(:a, :b, :event) }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Relationship, " when interpreting the label" do
+    it "should default to an event of nil" do
+        @edge = Puppet::Relationship.new(:a, :b)
+        @edge.event.should be_nil
+    end
+
+    it "should expose a provided event via the :event method" do
+        @edge = Puppet::Relationship.new(:a, :b, :event => :something, :callback => :whatever)
+        @edge.event.should == :something
+    end
+
+    it "should default to a nil callback" do
+        @edge = Puppet::Relationship.new(:a, :b)
+        @edge.callback.should be_nil
+    end
+
+    it "should expose a provided callback via the :callback method" do
+        @edge = Puppet::Relationship.new(:a, :b, :callback => :testing)
+        @edge.callback.should == :testing
+    end
+end
+
+describe Puppet::Relationship, " when matching edges with no specified event" do
+    before do
+        @edge = Puppet::Relationship.new(:a, :b)
+    end
+
+    it "should not match :NONE" do
+        @edge.should_not be_match(:NONE)
+    end
+
+    it "should not match :ALL_EVENTS" do
+        @edge.should_not be_match(:NONE)
+    end
+
+    it "should not match any other events" do
+        @edge.should_not be_match(:whatever)
+    end
+end
+
+describe Puppet::Relationship, " when matching edges with :NONE as the event" do
+    before do
+        @edge = Puppet::Relationship.new(:a, :b, :event => :NONE)
+    end
+    it "should not match :NONE" do
+        @edge.should_not be_match(:NONE)
+    end
+
+    it "should not match :ALL_EVENTS" do
+        @edge.should_not be_match(:ALL_EVENTS)
+    end
+
+    it "should not match other events" do
+        @edge.should_not be_match(:yayness)
+    end
+end
+
+describe Puppet::Relationship, " when matching edges with :ALL as the event" do
+    before do
+        @edge = Puppet::Relationship.new(:a, :b, :event => :ALL_EVENTS, :callback => :whatever)
+    end
+
+    it "should not match :NONE" do
+        @edge.should_not be_match(:NONE)
+    end
+
+    it "should match :ALL_EVENTS" do
+        @edge.should be_match(:ALLEVENTS)
+    end
+
+    it "should match all other events" do
+        @edge.should be_match(:foo)
+    end
+end
+
+describe Puppet::Relationship, " when matching edges with a non-standard event" do
+    before do
+        @edge = Puppet::Relationship.new(:a, :b, :event => :random, :callback => :whatever)
+    end
+
+    it "should not match :NONE" do
+        @edge.should_not be_match(:NONE)
+    end
+
+    it "should not match :ALL_EVENTS" do
+        @edge.should_not be_match(:ALL_EVENTS)
+    end
+
+    it "should match events with the same name" do
+        @edge.should be_match(:random)
+    end
+end
diff --git a/spec/unit/reports.rb b/spec/unit/reports.rb
new file mode 100755
index 0000000..f12f0d7
--- /dev/null
+++ b/spec/unit/reports.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/reports'
+
+describe Puppet::Reports do
+    it "should instance-load report types" do
+        Puppet::Reports.instance_loader(:report).should be_instance_of(Puppet::Util::Autoload)
+    end
+
+    it "should have a method for registering report types" do
+        Puppet::Reports.should respond_to(:register_report)
+    end
+
+    it "should have a method for retrieving report types by name" do
+        Puppet::Reports.should respond_to(:report)
+    end
+
+    it "should provide a method for returning documentation for all reports" do
+        Puppet::Reports.expects(:loaded_instances).with(:report).returns([:one, :two])
+        one = mock 'one', :doc => "onedoc"
+        two = mock 'two', :doc => "twodoc"
+        Puppet::Reports.expects(:report).with(:one).returns(one)
+        Puppet::Reports.expects(:report).with(:two).returns(two)
+
+        doc = Puppet::Reports.reportdocs
+        doc.include?("onedoc").should be_true
+        doc.include?("twodoc").should be_true
+    end
+end
+
+
+describe Puppet::Reports, " when loading report types" do
+    it "should use the instance loader to retrieve report types" do
+        Puppet::Reports.expects(:loaded_instance).with(:report, :myreporttype)
+        Puppet::Reports.report(:myreporttype)
+    end
+end
+
+describe Puppet::Reports, " when registering report types" do
+    it "should evaluate the supplied block as code for a module" do
+        Puppet::Reports.expects(:genmodule).returns(Module.new)
+        Puppet::Reports.register_report(:testing) { }
+    end
+
+    it "should extend the report type with the Puppet::Util::Docs module" do
+        mod = stub 'module', :define_method => true
+
+        Puppet::Reports.expects(:genmodule).with { |name, options, block| options[:extend] == Puppet::Util::Docs }.returns(mod)
+        Puppet::Reports.register_report(:testing) { }
+    end
+
+    it "should define a :report_name method in the module that returns the name of the report" do
+        mod = mock 'module'
+        mod.expects(:define_method).with(:report_name)
+
+        Puppet::Reports.expects(:genmodule).returns(mod)
+        Puppet::Reports.register_report(:testing) { }
+    end
+end
diff --git a/spec/unit/resource_reference.rb b/spec/unit/resource_reference.rb
new file mode 100755
index 0000000..cbbd6ef
--- /dev/null
+++ b/spec/unit/resource_reference.rb
@@ -0,0 +1,73 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+require 'puppet/resource_reference'
+
+describe Puppet::ResourceReference do
+    it "should have a :title attribute" do
+        Puppet::ResourceReference.new(:file, "foo").title.should == "foo"
+    end
+
+    it "should canonize types to capitalized strings" do
+        Puppet::ResourceReference.new(:file, "foo").type.should == "File"
+    end
+
+    it "should canonize qualified types so all strings are capitalized" do
+        Puppet::ResourceReference.new("foo::bar", "foo").type.should == "Foo::Bar"
+    end
+
+    it "should set its type to 'Class' and its title to the passed title if the passed type is :component and the title has no square brackets in it" do
+        ref = Puppet::ResourceReference.new(:component, "foo")
+        ref.type.should == "Class"
+        ref.title.should == "foo"
+    end
+
+    it "should interpret the title as a reference and assign appropriately if the type is :component and the title contains square brackets" do
+        ref = Puppet::ResourceReference.new(:component, "foo::bar[yay]")
+        ref.type.should == "Foo::Bar"
+        ref.title.should == "yay"
+    end
+
+    it "should set the type to 'Class' if it is nil and the title contains no square brackets" do
+        ref = Puppet::ResourceReference.new(nil, "yay")
+        ref.type.should == "Class"
+        ref.title.should == "yay"
+    end
+
+    it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains square brackets" do
+        ref = Puppet::ResourceReference.new(nil, "foo::bar[yay]")
+        ref.type.should == "Foo::Bar"
+        ref.title.should == "yay"
+    end
+
+    it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains nested square brackets" do
+        ref = Puppet::ResourceReference.new(nil, "foo::bar[baz[yay]]")
+        ref.type.should == "Foo::Bar"
+        ref.title.should =="baz[yay]"
+    end
+end
+
+describe Puppet::ResourceReference, "when resolving resources without a catalog" do
+    it "should be able to resolve builtin resources from their types" do
+        Puppet::Type.type(:file).expects(:[]).with("myfile").returns(:myfile)
+        Puppet::ResourceReference.new(:file, "myfile").resolve.should == :myfile
+    end
+
+    it "should be able to resolve defined resources from Components" do
+        Puppet::Type.type(:component).expects(:[]).with("Foo::Bar[yay]").returns(:mything)
+        Puppet::ResourceReference.new("foo::bar", "yay").resolve.should == :mything
+    end
+end
+
+describe Puppet::ResourceReference, "when resolving resources with a catalog" do
+    it "should resolve all resources using the catalog" do
+        config = mock 'catalog'
+        ref = Puppet::ResourceReference.new("foo::bar", "yay")
+        ref.catalog = config
+
+        config.expects(:resource).with("Foo::Bar[yay]").returns(:myresource)
+
+        ref.resolve.should == :myresource
+    end
+end
diff --git a/spec/unit/simple_graph.rb b/spec/unit/simple_graph.rb
new file mode 100755
index 0000000..e1e42e4
--- /dev/null
+++ b/spec/unit/simple_graph.rb
@@ -0,0 +1,280 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-11-1.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../spec_helper'
+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.size.should == 2
+    end
+
+    it "should consider itself a directed graph" do
+        Puppet::SimpleGraph.new.directed?.should be_true
+    end
+
+    it "should provide a method for reversing the graph" do
+        @graph = Puppet::SimpleGraph.new
+        @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)
+
+        proc { @graph.to_dot_graph }.should_not raise_error
+    end
+end
+
+describe Puppet::SimpleGraph, " when managing vertices" do
+    before do
+        @graph = Puppet::SimpleGraph.new
+    end
+
+    it "should provide a method to add a vertex" do
+        @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
+    end
+
+    it "should return true when asked if a vertex is present" do
+        @graph.add_vertex(:test)
+        @graph.vertex?(:test).should be_true
+    end
+
+    it "should return false when asked if a non-vertex is present" do
+        @graph.vertex?(:test).should be_false
+    end
+
+    it "should return all set vertices when asked" do
+        @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.remove_vertex!(:one)
+        @graph.vertex?(:one).should be_false
+    end
+
+    it "should do nothing when a non-vertex is asked to be removed" do
+        proc { @graph.remove_vertex!(:one) }.should_not raise_error
+    end
+end
+
+describe Puppet::SimpleGraph, " when managing edges" do
+    before do
+        @graph = Puppet::SimpleGraph.new
+    end
+
+    it "should provide a method to test whether a given vertex pair is an edge" do
+        @graph.should respond_to(:edge?)
+    end
+
+    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.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.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.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.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.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.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.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)
+        edges = @graph.edges
+        edges.length.should == 2
+        edges.should include(one)
+        edges.should include(two)
+    end
+
+    it "should remove an edge when asked" do
+        edge = Puppet::Relationship.new(:one, :two)
+        @graph.add_edge(edge)
+        @graph.remove_edge!(edge)
+        @graph.edge?(edge.source, edge.target).should be_false
+    end
+
+    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.remove_vertex!(:two)
+        @graph.edge?(:one, :two).should be_false
+        @graph.edge?(:two, :three).should be_false
+        @graph.edges.length.should == 0
+    end
+end
+
+describe Puppet::SimpleGraph, " when finding adjacent vertices" do
+    before do
+        @graph = Puppet::SimpleGraph.new
+        @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)
+    end
+
+    it "should return adjacent vertices" do
+        adj = @graph.adjacent(:one)
+        adj.should be_include(:three)
+        adj.should be_include(:two)
+    end
+
+    it "should default to finding :out vertices" do
+        @graph.adjacent(:two).should == [:three]
+    end
+
+    it "should support selecting :in vertices" do
+        @graph.adjacent(:two, :direction => :in).should == [:one]
+    end
+
+    it "should default to returning the matching vertices as an array of vertices" do
+        @graph.adjacent(:two).should == [:three]
+    end
+
+    it "should support returning an array of matching edges" do
+        @graph.adjacent(:two, :type => :edges).should == [@two_three]
+    end
+end
+
+describe Puppet::SimpleGraph, " when clearing" do
+    before 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.clear
+    end
+
+    it "should remove all vertices" do
+        @graph.vertices.should be_empty
+    end
+
+    it "should remove all edges" do
+        @graph.edges.should be_empty
+    end
+end
+
+describe Puppet::SimpleGraph, " when reversing graphs" do
+    before do
+        @graph = Puppet::SimpleGraph.new
+    end
+
+    it "should provide a method for reversing the graph" do
+        @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.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)
+        edge = @graph.reversal.edge(:two, :one)
+        edge.label.should == {:stuff => :awesome}
+    end
+end
+
+describe Puppet::SimpleGraph, " when sorting the graph" do
+    before do
+        @graph = Puppet::SimpleGraph.new
+    end
+
+    def add_edges(hash)
+        hash.each do |a,b|
+            @graph.add_edge(a, b)
+        end
+    end
+
+    it "should sort the graph topologically" do
+        add_edges :a => :b, :b => :c
+        @graph.topsort.should == [:a, :b, :c]
+    end
+
+    it "should fail on two-vertex loops" do
+        add_edges :a => :b, :b => :a
+        proc { @graph.topsort }.should raise_error(Puppet::Error)
+    end
+
+    it "should fail on multi-vertex loops" do
+        add_edges :a => :b, :b => :c, :c => :a
+        proc { @graph.topsort }.should raise_error(Puppet::Error)
+    end
+
+    it "should fail when a larger tree contains a small cycle" do
+        add_edges :a => :b, :b => :a, :c => :a, :d => :c
+        proc { @graph.topsort }.should raise_error(Puppet::Error)
+    end
+
+    it "should succeed on trees with no cycles" do
+        add_edges :a => :b, :b => :e, :c => :a, :d => :c
+        proc { @graph.topsort }.should_not raise_error
+    end
+
+    # Our graph's add_edge method is smart enough not to add
+    # duplicate edges, so we use the objects, which it doesn't
+    # check.
+    it "should be able to sort graphs with duplicate edges" do
+        one = Puppet::Relationship.new(:a, :b)
+        @graph.add_edge(one)
+        two = Puppet::Relationship.new(:a, :b)
+        @graph.add_edge(two)
+        proc { @graph.topsort }.should_not raise_error
+    end
+end
diff --git a/spec/unit/transaction/report.rb b/spec/unit/transaction/report.rb
new file mode 100755
index 0000000..644f8d7
--- /dev/null
+++ b/spec/unit/transaction/report.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-12.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/transaction/report'
+
+describe Puppet::Transaction::Report, " when being indirect" do
+    it "should redirect :find to the indirection" do
+        @indirection = stub 'indirection', :name => :report
+        Puppet::Transaction::Report.stubs(:indirection).returns(@indirection)
+        @indirection.expects(:find)
+        Puppet::Transaction::Report.find(:report)
+    end
+
+    it "should redirect :save to the indirection" do
+        Facter.stubs(:value).returns("eh")
+        @indirection = stub 'indirection', :name => :report
+        Puppet::Transaction::Report.stubs(:indirection).returns(@indirection)
+        report = Puppet::Transaction::Report.new
+        @indirection.expects(:save)
+        report.save
+    end
+
+    it "should default to the 'processor' terminus" do
+        Puppet::Transaction::Report.indirection.terminus_class.should == :processor
+    end
+
+    it "should delegate its name attribute to its host method" do
+        report = Puppet::Transaction::Report.new
+        report.expects(:host).returns "me"
+        report.name.should == "me"
+    end
+
+    after do
+        Puppet::Indirector::Indirection.clear_cache
+    end
+end
diff --git a/spec/unit/util/checksums.rb b/spec/unit/util/checksums.rb
new file mode 100755
index 0000000..0e0d06c
--- /dev/null
+++ b/spec/unit/util/checksums.rb
@@ -0,0 +1,99 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-9-22.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/util/checksums'
+
+describe Puppet::Util::Checksums do
+    before do
+        @summer = Object.new
+        @summer.extend(Puppet::Util::Checksums)
+    end
+
+    content_sums = [:md5, :md5lite, :sha1, :sha1lite]
+    file_only = [:ctime, :mtime]
+
+    content_sums.each do |sumtype|
+        it "should be able to calculate %s sums from strings" % sumtype do
+            @summer.should be_respond_to(sumtype)
+        end
+    end
+
+    [content_sums, file_only].flatten.each do |sumtype|
+        it "should be able to calculate %s sums from files" % sumtype do
+            @summer.should be_respond_to(sumtype.to_s + "_file")
+        end
+    end
+
+    {:md5 => Digest::MD5, :sha1 => Digest::SHA1}.each do |sum, klass|
+        describe("when using %s" % sum) do
+            it "should use #{klass} to calculate string checksums" do
+                klass.expects(:hexdigest).with("mycontent").returns "whatever"
+                @summer.send(sum, "mycontent").should == "whatever"
+            end
+
+            it "should use incremental #{klass} sums to calculate file checksums" do
+                digest = mock 'digest'
+                klass.expects(:new).returns digest
+
+                file = "/path/to/my/file"
+
+                fh = mock 'filehandle'
+                fh.expects(:read).with(512).times(3).returns("firstline").then.returns("secondline").then.returns(nil)
+                #fh.expects(:read).with(512).returns("secondline")
+                #fh.expects(:read).with(512).returns(nil)
+
+                File.expects(:open).with(file, "r").yields(fh)
+
+                digest.expects(:<<).with "firstline"
+                digest.expects(:<<).with "secondline"
+                digest.expects(:hexdigest).returns :mydigest
+
+                @summer.send(sum.to_s + "_file", file).should == :mydigest
+            end
+        end
+    end
+
+    {:md5lite => Digest::MD5, :sha1lite => Digest::SHA1}.each do |sum, klass|
+        describe("when using %s" % sum) do
+            it "should use #{klass} to calculate string checksums from the first 512 characters of the string" do
+                content = "this is a test" * 100
+                klass.expects(:hexdigest).with(content[0..511]).returns "whatever"
+                @summer.send(sum, content).should == "whatever"
+            end
+
+            it "should use #{klass} to calculate a sum from the first 512 characters in the file" do
+                digest = mock 'digest'
+                klass.expects(:new).returns digest
+
+                file = "/path/to/my/file"
+
+                fh = mock 'filehandle'
+                fh.expects(:read).with(512).returns('my content')
+
+                File.expects(:open).with(file, "r").yields(fh)
+
+                digest.expects(:<<).with "my content"
+                digest.expects(:hexdigest).returns :mydigest
+
+                @summer.send(sum.to_s + "_file", file).should == :mydigest
+            end
+        end
+    end
+
+    [:ctime, :mtime].each do |sum|
+        describe("when using %s" % sum) do
+            it "should use the '#{sum}' on the file to determine the ctime" do
+                file = "/my/file"
+                stat = mock 'stat', sum => "mysum"
+
+                File.expects(:stat).with(file).returns(stat)
+
+                @summer.send(sum.to_s + "_file", file).should == "mysum"
+            end
+        end
+    end
+end
diff --git a/spec/unit/util/constant_inflector.rb b/spec/unit/util/constant_inflector.rb
new file mode 100755
index 0000000..5112e73
--- /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/loadedfile.rb b/spec/unit/util/loadedfile.rb
new file mode 100755
index 0000000..083120e
--- /dev/null
+++ b/spec/unit/util/loadedfile.rb
@@ -0,0 +1,65 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'tempfile'
+require 'puppet/util/loadedfile'
+
+describe Puppet::Util::LoadedFile do
+    before(:each) do
+        @f = Tempfile.new('loadedfile_test')
+        @f.puts "yayness"
+        @f.flush
+
+        @loaded = Puppet::Util::LoadedFile.new(@f.path)
+
+        fake_ctime = Time.now - (2 * Puppet[:filetimeout])
+        @stat = stub('stat', :ctime => fake_ctime)
+        @fake_now = Time.now + (2 * Puppet[:filetimeout])
+    end
+
+    it "should recognize when the file has not changed" do
+        # Use fake "now" so that we can be sure changed? actually checks, without sleeping
+        # for Puppet[:filetimeout] seconds.
+        Time.stubs(:now).returns(@fake_now)
+        @loaded.changed?.should == false
+    end
+
+    it "should recognize when the file has changed" do
+        # Fake File.stat so we don't have to depend on the filesystem granularity. Doing a flush()
+        # just didn't do the job.
+        File.stubs(:stat).returns(@stat)
+        # Use fake "now" so that we can be sure changed? actually checks, without sleeping
+        # for Puppet[:filetimeout] seconds.
+        Time.stubs(:now).returns(@fake_now)
+        @loaded.changed?.should be_an_instance_of(Time)
+    end
+
+    it "should not catch a change until the timeout has elapsed" do
+        # Fake File.stat so we don't have to depend on the filesystem granularity. Doing a flush()
+        # just didn't do the job.
+        File.stubs(:stat).returns(@stat)
+        @loaded.changed?.should be(false)
+        # Use fake "now" so that we can be sure changed? actually checks, without sleeping
+        # for Puppet[:filetimeout] seconds.
+        Time.stubs(:now).returns(@fake_now)
+        @loaded.changed?.should_not be(false)
+    end
+
+    it "should consider a file changed when that file is missing" do
+        @f.close!
+        # Use fake "now" so that we can be sure changed? actually checks, without sleeping
+        # for Puppet[:filetimeout] seconds.
+        Time.stubs(:now).returns(@fake_now)
+        @loaded.changed?.should_not be(false)
+    end
+
+    it "should disable checking if Puppet[:filetimeout] is negative" do
+        Puppet[:filetimeout] = -1
+        @loaded.changed?.should_not be(false)
+    end
+
+    after(:each) do
+        @f.close
+    end
+end
diff --git a/spec/unit/util/nagios_maker.rb b/spec/unit/util/nagios_maker.rb
new file mode 100755
index 0000000..b754394
--- /dev/null
+++ b/spec/unit/util/nagios_maker.rb
@@ -0,0 +1,128 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-11-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/util/nagios_maker'
+
+describe Puppet::Util::NagiosMaker do
+    before do
+        @module = Puppet::Util::NagiosMaker
+
+        @nagtype = stub 'nagios type', :parameters => [], :namevar => :name
+        Nagios::Base.stubs(:type).with(:test).returns(@nagtype)
+    end
+
+    it "should be able to create a new nagios type" do
+        @module.should respond_to(:create_nagios_type)
+    end
+
+    it "should fail if it cannot find the named Naginator type" do
+        Nagios::Base.stubs(:type).returns(nil)
+
+        lambda { @module.create_nagios_type(:no_such_type) }.should raise_error(Puppet::DevError)
+    end
+
+    it "should create a new RAL type with the provided name prefixed with 'nagios_'" do
+        type = stub 'type', :newparam => nil, :newproperty => nil, :ensurable => nil, :provide => nil, :desc => nil
+
+        Puppet::Type.expects(:newtype).with(:nagios_test).returns(type)
+        @module.create_nagios_type(:test)
+    end
+
+    it "should mark the created type as ensurable" do
+        type = stub 'type', :newparam => nil, :newproperty => nil, :provide => nil, :desc => nil
+
+        type.expects(:ensurable)
+
+        Puppet::Type.expects(:newtype).with(:nagios_test).returns(type)
+        @module.create_nagios_type(:test)
+    end
+
+    it "should create a namevar parameter for the nagios type's name parameter" do
+        type = stub 'type', :newproperty => nil, :ensurable => nil, :provide => nil, :desc => nil
+
+        type.expects(:newparam).with(:name, :namevar => true)
+
+        Puppet::Type.expects(:newtype).with(:nagios_test).returns(type)
+        @module.create_nagios_type(:test)
+    end
+
+    it "should create a property for all non-namevar parameters" do
+        type = stub 'type', :newparam => nil, :ensurable => nil, :provide => nil, :desc => nil
+
+        @nagtype.stubs(:parameters).returns([:one, :two])
+
+        type.expects(:newproperty).with(:one)
+        type.expects(:newproperty).with(:two)
+        type.expects(:newproperty).with(:target)
+
+        Puppet::Type.expects(:newtype).with(:nagios_test).returns(type)
+        @module.create_nagios_type(:test)
+    end
+
+    it "should skip parameters that start with integers" do
+        type = stub 'type', :newparam => nil, :ensurable => nil, :provide => nil, :desc => nil
+
+        @nagtype.stubs(:parameters).returns(["2dcoords".to_sym, :other])
+
+        type.expects(:newproperty).with(:other)
+        type.expects(:newproperty).with(:target)
+
+        Puppet::Type.expects(:newtype).with(:nagios_test).returns(type)
+        @module.create_nagios_type(:test)
+    end
+
+    it "should deduplicate the parameter list" do
+        type = stub 'type', :newparam => nil, :ensurable => nil, :provide => nil, :desc => nil
+
+        @nagtype.stubs(:parameters).returns([:one, :one])
+
+        type.expects(:newproperty).with(:one)
+        type.expects(:newproperty).with(:target)
+
+        Puppet::Type.expects(:newtype).with(:nagios_test).returns(type)
+        @module.create_nagios_type(:test)
+    end
+
+    it "should create a target property" do
+        type = stub 'type', :newparam => nil, :ensurable => nil, :provide => nil, :desc => nil
+
+        type.expects(:newproperty).with(:target)
+
+        Puppet::Type.expects(:newtype).with(:nagios_test).returns(type)
+        @module.create_nagios_type(:test)
+    end
+end
+
+describe Puppet::Util::NagiosMaker, " when creating the naginator provider" do
+    before do
+        @module = Puppet::Util::NagiosMaker
+
+        @nagtype = stub 'nagios type', :parameters => [], :namevar => :name
+        Nagios::Base.stubs(:type).with(:test).returns(@nagtype)
+
+        @type = stub 'type', :newparam => nil, :ensurable => nil, :newproperty => nil, :desc => nil
+        Puppet::Type.stubs(:newtype).with(:nagios_test).returns(@type)
+    end
+
+    it "should add a naginator provider" do
+        @type.expects(:provide).with { |name, options| name == :naginator }
+
+        @module.create_nagios_type(:test)
+    end
+
+    it "should set Puppet::Provider::Naginator as the parent class of the provider" do
+        @type.expects(:provide).with { |name, options| options[:parent] == Puppet::Provider::Naginator }
+
+        @module.create_nagios_type(:test)
+    end
+
+    it "should use /etc/nagios/$name.cfg as the default target" do
+        @type.expects(:provide).with { |name, options| options[:default_target] == "/etc/nagios/nagios_test.cfg" }
+
+        @module.create_nagios_type(:test)
+    end
+end
diff --git a/spec/unit/util/settings.rb b/spec/unit/util/settings.rb
new file mode 100755
index 0000000..a6b3584
--- /dev/null
+++ b/spec/unit/util/settings.rb
@@ -0,0 +1,706 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Util::Settings, " when specifying defaults" do
+    before do
+        @settings = Puppet::Util::Settings.new
+    end
+
+    it "should start with no defined parameters" do
+        @settings.params.length.should == 0
+    end
+
+    it "should allow specification of default values associated with a section as an array" do
+        @settings.setdefaults(:section, :myvalue => ["defaultval", "my description"])
+    end
+
+    it "should not allow duplicate parameter specifications" do
+        @settings.setdefaults(:section, :myvalue => ["a", "b"])
+        lambda { @settings.setdefaults(:section, :myvalue => ["c", "d"]) }.should raise_error(ArgumentError)
+    end
+
+    it "should allow specification of default values associated with a section as a hash" do
+        @settings.setdefaults(:section, :myvalue => {:default => "defaultval", :desc => "my description"})
+    end
+
+    it "should consider defined parameters to be valid" do
+        @settings.setdefaults(:section, :myvalue => ["defaultval", "my description"])
+        @settings.valid?(:myvalue).should be_true
+    end
+
+    it "should require a description when defaults are specified with an array" do
+        lambda { @settings.setdefaults(:section, :myvalue => ["a value"]) }.should raise_error(ArgumentError)
+    end
+
+    it "should require a description when defaults are specified with a hash" do
+        lambda { @settings.setdefaults(:section, :myvalue => {:default => "a value"}) }.should raise_error(ArgumentError)
+    end
+
+    it "should support specifying owner, group, and mode when specifying files" do
+        @settings.setdefaults(:section, :myvalue => {:default => "/some/file", :owner => "blah", :mode => "boo", :group => "yay", :desc => "whatever"})
+    end
+
+    it "should support specifying a short name" do
+        @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"})
+    end
+
+    it "should fail when short names conflict" do
+        @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"})
+        lambda { @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"}) }.should raise_error(ArgumentError)
+    end
+end
+
+describe Puppet::Util::Settings, " when setting values" do
+    before do
+        @settings = Puppet::Util::Settings.new
+        @settings.setdefaults :main, :myval => ["val", "desc"]
+        @settings.setdefaults :main, :bool => [true, "desc"]
+    end
+
+    it "should provide a method for setting values from other objects" do
+        @settings[:myval] = "something else"
+        @settings[:myval].should == "something else"
+    end
+
+    it "should support a getopt-specific mechanism for setting values" do
+        @settings.handlearg("--myval", "newval")
+        @settings[:myval].should == "newval"
+    end
+
+    it "should support a getopt-specific mechanism for turning booleans off" do
+        @settings.handlearg("--no-bool")
+        @settings[:bool].should == false
+    end
+
+    it "should support a getopt-specific mechanism for turning booleans on" do
+        # Turn it off first
+        @settings[:bool] = false
+        @settings.handlearg("--bool")
+        @settings[:bool].should == true
+    end
+
+    it "should clear the cache when setting getopt-specific values" do
+        @settings.setdefaults :mysection, :one => ["whah", "yay"], :two => ["$one yay", "bah"]
+        @settings[:two].should == "whah yay"
+        @settings.handlearg("--one", "else")
+        @settings[:two].should == "else yay"
+    end
+
+    it "should not clear other values when setting getopt-specific values" do
+        @settings[:myval] = "yay"
+        @settings.handlearg("--no-bool")
+        @settings[:myval].should == "yay"
+    end
+
+    it "should call passed blocks when values are set" do
+        values = []
+        @settings.setdefaults(:section, :hooker => {:default => "yay", :desc => "boo", :hook => lambda { |v| values << v }})
+        values.should == []
+
+        @settings[:hooker] = "something"
+        values.should == %w{something}
+    end
+
+    it "should provide an option to call passed blocks during definition" do
+        values = []
+        @settings.setdefaults(:section, :hooker => {:default => "yay", :desc => "boo", :call_on_define => true, :hook => lambda { |v| values << v }})
+        values.should == %w{yay}
+    end
+
+    it "should pass the fully interpolated value to the hook when called on definition" do
+        values = []
+        @settings.setdefaults(:section, :one => ["test", "a"])
+        @settings.setdefaults(:section, :hooker => {:default => "$one/yay", :desc => "boo", :call_on_define => true, :hook => lambda { |v| values << v }})
+        values.should == %w{test/yay}
+    end
+
+    it "should munge values using the element-specific methods" do
+        @settings[:bool] = "false"
+        @settings[:bool].should == false
+    end
+
+    it "should prefer cli values to values set in Ruby code" do
+        @settings.handlearg("--myval", "cliarg")
+        @settings[:myval] = "memarg"
+        @settings[:myval].should == "cliarg"
+    end
+end
+
+describe Puppet::Util::Settings, " when returning values" do
+    before do
+        @settings = Puppet::Util::Settings.new
+        @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"], :four => ["$two $three FOUR", "d"]
+    end
+
+    it "should provide a mechanism for returning set values" do
+        @settings[:one] = "other"
+        @settings[:one].should == "other"
+    end
+
+    it "should interpolate default values for other parameters into returned parameter values" do
+        @settings[:one].should == "ONE"
+        @settings[:two].should == "ONE TWO"
+        @settings[:three].should == "ONE ONE TWO THREE"
+    end
+
+    it "should interpolate default values that themselves need to be interpolated" do
+        @settings[:four].should == "ONE TWO ONE ONE TWO THREE FOUR"
+    end
+
+    it "should interpolate set values for other parameters into returned parameter values" do
+        @settings[:one] = "on3"
+        @settings[:two] = "$one tw0"
+        @settings[:three] = "$one $two thr33"
+        @settings[:four] = "$one $two $three f0ur"
+        @settings[:one].should == "on3"
+        @settings[:two].should == "on3 tw0"
+        @settings[:three].should == "on3 on3 tw0 thr33"
+        @settings[:four].should == "on3 on3 tw0 on3 on3 tw0 thr33 f0ur"
+    end
+
+    it "should not cache interpolated values such that stale information is returned" do
+        @settings[:two].should == "ONE TWO"
+        @settings[:one] = "one"
+        @settings[:two].should == "one TWO"
+    end
+
+    it "should not cache values such that information from one environment is returned for another environment" do
+        text = "[env1]\none = oneval\n[env2]\none = twoval\n"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/whatever")
+        @settings.stubs(:read_file).with(file).returns(text)
+        @settings.parse(file)
+
+        @settings.value(:one, "env1").should == "oneval"
+        @settings.value(:one, "env2").should == "twoval"
+    end
+
+    it "should have a name determined by the 'name' parameter" do
+        @settings.setdefaults(:whatever, :name => ["something", "yayness"])
+        @settings.name.should == :something
+        @settings[:name] = :other
+        @settings.name.should == :other
+    end
+end
+
+describe Puppet::Util::Settings, " when choosing which value to return" do
+    before do
+        @settings = Puppet::Util::Settings.new
+        @settings.setdefaults :section,
+            :one => ["ONE", "a"],
+            :name => ["myname", "w"]
+    end
+
+    it "should return default values if no values have been set" do
+        @settings[:one].should == "ONE"
+    end
+
+    it "should return values set on the cli before values set in the configuration file" do
+        text = "[main]\none = fileval\n"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/whatever")
+        @settings.stubs(:parse_file).returns(text)
+        @settings.handlearg("--one", "clival")
+        @settings.parse(file)
+
+        @settings[:one].should == "clival"
+    end
+
+    it "should return values set on the cli before values set in Ruby" do
+        @settings[:one] = "rubyval"
+        @settings.handlearg("--one", "clival")
+        @settings[:one].should == "clival"
+    end
+
+    it "should return values set in the executable-specific section before values set in the main section" do
+        text = "[main]\none = mainval\n[myname]\none = nameval\n"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/whatever")
+        @settings.stubs(:read_file).with(file).returns(text)
+        @settings.parse(file)
+
+        @settings[:one].should == "nameval"
+    end
+
+    it "should not return values outside of its search path" do
+        text = "[other]\none = oval\n"
+        file = "/some/file"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/whatever")
+        @settings.stubs(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings[:one].should == "ONE"
+    end
+
+    it "should return values in a specified environment" do
+        text = "[env]\none = envval\n"
+        file = "/some/file"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/whatever")
+        @settings.stubs(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings.value(:one, "env").should == "envval"
+    end
+
+    it "should return values in a specified environment before values in the main or name sections" do
+        text = "[env]\none = envval\n[main]\none = mainval\n[myname]\none = nameval\n"
+        file = "/some/file"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/whatever")
+        @settings.stubs(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings.value(:one, "env").should == "envval"
+    end
+end
+
+describe Puppet::Util::Settings, " when parsing its configuration" do
+    before do
+        @settings = Puppet::Util::Settings.new
+        @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"]
+    end
+
+    it "should return values set in the configuration file" do
+        text = "[main]
+        one = fileval
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings[:one].should == "fileval"
+    end
+
+    #484 - this should probably be in the regression area
+    it "should not throw an exception on unknown parameters" do
+        text = "[main]\nnosuchparam = mval\n"
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        lambda { @settings.parse(file) }.should_not raise_error
+    end
+
+    it "should support an old parse method when per-executable configuration files still exist" do
+        # I'm not going to bother testing this method.
+        @settings.should respond_to(:old_parse)
+    end
+
+    it "should convert booleans in the configuration file into Ruby booleans" do
+        text = "[main]
+        one = true
+        two = false
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings[:one].should == true
+        @settings[:two].should == false
+    end
+
+    it "should convert integers in the configuration file into Ruby Integers" do
+        text = "[main]
+        one = 65
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings[:one].should == 65
+    end
+
+    it "should support specifying all metadata (owner, group, mode) in the configuration file" do
+        @settings.setdefaults :section, :myfile => ["/myfile", "a"]
+
+        text = "[main]
+        myfile = /other/file {owner = luke, group = luke, mode = 644}
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings[:myfile].should == "/other/file"
+        @settings.metadata(:myfile).should == {:owner => "luke", :group => "luke", :mode => "644"}
+    end
+
+    it "should support specifying a single piece of metadata (owner, group, or mode) in the configuration file" do
+        @settings.setdefaults :section, :myfile => ["/myfile", "a"]
+
+        text = "[main]
+        myfile = /other/file {owner = luke}
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings[:myfile].should == "/other/file"
+        @settings.metadata(:myfile).should == {:owner => "luke"}
+    end
+
+    it "should call hooks associated with values set in the configuration file" do
+        values = []
+        @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }}
+
+        text = "[main]
+        mysetting = setval
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        values.should == ["setval"]
+    end
+
+    it "should not call the same hook for values set multiple times in the configuration file" do
+        values = []
+        @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }}
+
+        text = "[main]
+        mysetting = setval
+        [puppet]
+        mysetting = other
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        values.should == ["setval"]
+    end
+
+    it "should pass the environment-specific value to the hook when one is available" do
+        values = []
+        @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }}
+        @settings.setdefaults :section, :environment => ["yay", "a"]
+        @settings.setdefaults :section, :environments => ["yay,foo", "a"]
+
+        text = "[main]
+        mysetting = setval
+        [yay]
+        mysetting = other
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        values.should == ["other"]
+    end
+
+    it "should pass the interpolated value to the hook when one is available" do
+        values = []
+        @settings.setdefaults :section, :base => {:default => "yay", :desc => "a", :hook => proc { |v| values << v }}
+        @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }}
+
+        text = "[main]
+        mysetting = $base/setval
+        "
+        file = "/some/file"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        values.should == ["yay/setval"]
+    end
+
+    it "should allow empty values" do
+        @settings.setdefaults :section, :myarg => ["myfile", "a"]
+
+        text = "[main]
+        myarg =
+        "
+        @settings.stubs(:read_file).returns(text)
+        @settings.parse("/some/file")
+        @settings[:myarg].should == ""
+    end
+end
+
+describe Puppet::Util::Settings, " when reparsing its configuration" do
+    before do
+        @settings = Puppet::Util::Settings.new
+        @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"]
+    end
+
+    it "should replace in-memory values with on-file values" do
+        # Init the value
+        text = "[main]\none = disk-init\n"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/test/file")
+        @settings[:one] = "init"
+        @settings.file = file
+
+        # Now replace the value
+        text = "[main]\none = disk-replace\n"
+        
+        # This is kinda ridiculous - the reason it parses twice is that
+        # it goes to parse again when we ask for the value, because the
+        # mock always says it should get reparsed.
+        @settings.expects(:read_file).with(file).returns(text).times(2)
+        @settings.reparse
+        @settings[:one].should == "disk-replace"
+    end
+
+    it "should retain parameters set by cli when configuration files are reparsed" do
+        @settings.handlearg("--one", "clival")
+
+        text = "[main]\none = on-disk\n"
+        file = mock 'file'
+        file.stubs(:file).returns("/test/file")
+        @settings.stubs(:read_file).with(file).returns(text)
+        @settings.parse(file)
+
+        @settings[:one].should == "clival"
+    end
+
+    it "should remove in-memory values that are no longer set in the file" do
+        # Init the value
+        text = "[main]\none = disk-init\n"
+        file = mock 'file'
+        file.stubs(:changed?).returns(true)
+        file.stubs(:file).returns("/test/file")
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        @settings[:one].should == "disk-init"
+
+        # Now replace the value
+        text = "[main]\ntwo = disk-replace\n"
+        @settings.expects(:read_file).with(file).returns(text)
+        @settings.parse(file)
+        #@settings.reparse
+
+        # The originally-overridden value should be replaced with the default
+        @settings[:one].should == "ONE"
+
+        # and we should now have the new value in memory
+        @settings[:two].should == "disk-replace"
+    end
+end
+
+describe Puppet::Util::Settings, " when being used to manage the host machine" do
+    before do
+        @settings = Puppet::Util::Settings.new
+        @settings.setdefaults :main, :maindir => ["/maindir", "a"], :seconddir => ["/seconddir", "a"]
+        @settings.setdefaults :other, :otherdir => {:default => "/otherdir", :desc => "a", :owner => "luke", :group => "johnny", :mode => 0755}
+        @settings.setdefaults :third, :thirddir => ["/thirddir", "b"]
+        @settings.setdefaults :files, :myfile => {:default => "/myfile", :desc => "a", :mode => 0755}
+    end
+
+    def stub_transaction
+        @bucket = mock 'bucket'
+        @config = mock 'config', :clear => nil
+        @trans = mock 'transaction'
+
+        @settings.expects(:to_transportable).with(:whatever).returns(@bucket)
+        @bucket.expects(:to_catalog).returns(@config)
+        @config.expects(:apply).yields(@trans)
+        @config.stubs(:host_config=)
+    end
+
+    it "should provide a method that writes files with the correct modes" do
+        pending "Not converted from test/unit yet"
+    end
+
+    it "should provide a method that creates directories with the correct modes" do
+        Puppet::Util::SUIDManager.expects(:asuser).with("luke", "johnny").yields
+        Dir.expects(:mkdir).with("/otherdir", 0755)
+        @settings.mkdir(:otherdir)
+    end
+
+    it "should be able to create needed directories in a single section" do
+        Dir.expects(:mkdir).with("/maindir")
+        Dir.expects(:mkdir).with("/seconddir")
+        @settings.use(:main)
+    end
+
+    it "should be able to create needed directories in multiple sections" do
+        Dir.expects(:mkdir).with("/maindir")
+        Dir.expects(:mkdir).with("/seconddir")
+        Dir.expects(:mkdir).with("/thirddir")
+        @settings.use(:main, :third)
+    end
+
+    it "should provide a method to trigger enforcing of file modes on existing files and directories" do
+        pending "Not converted from test/unit yet"
+    end
+
+    it "should provide a method to convert the file mode enforcement into a Puppet manifest" do
+        pending "Not converted from test/unit yet"
+    end
+
+    it "should create files when configured to do so with the :create parameter"
+
+    it "should provide a method to convert the file mode enforcement into transportable resources" do
+        # Make it think we're root so it tries to manage user and group.
+        Puppet.features.stubs(:root?).returns(true)
+        File.stubs(:exist?).with("/myfile").returns(true)
+        trans = nil
+        trans = @settings.to_transportable
+        resources = []
+        trans.delve { |obj| resources << obj if obj.is_a? Puppet::TransObject }
+        %w{/maindir /seconddir /otherdir /myfile}.each do |path|
+            obj = resources.find { |r| r.type == "file" and r.name == path }
+            if path.include?("dir")
+                obj[:ensure].should == :directory
+            else
+                # Do not create the file, just manage mode
+                obj[:ensure].should be_nil
+            end
+            obj.should be_instance_of(Puppet::TransObject)
+            case path
+            when "/otherdir":
+                obj[:owner].should == "luke"
+                obj[:group].should == "johnny"
+                obj[:mode].should == 0755
+            when "/myfile":
+                obj[:mode].should == 0755
+            end
+        end
+    end
+
+    it "should not try to manage user or group when not running as root" do
+        Puppet.features.stubs(:root?).returns(false)
+        trans = nil
+        trans = @settings.to_transportable(:other)
+        trans.delve do |obj|
+            next unless obj.is_a?(Puppet::TransObject)
+            obj[:owner].should be_nil
+            obj[:group].should be_nil
+        end
+    end
+
+    it "should add needed users and groups to the manifest when asked" do
+        # This is how we enable user/group management
+        @settings.setdefaults :main, :mkusers => [true, "w"]
+        Puppet.features.stubs(:root?).returns(false)
+        trans = nil
+        trans = @settings.to_transportable(:other)
+        resources = []
+        trans.delve { |obj| resources << obj if obj.is_a? Puppet::TransObject and obj.type != "file" }
+
+        user = resources.find { |r| r.type == "user" }
+        user.should be_instance_of(Puppet::TransObject)
+        user.name.should == "luke"
+        user[:ensure].should == :present
+
+        # This should maybe be a separate test, but...
+        group = resources.find { |r| r.type == "group" }
+        group.should be_instance_of(Puppet::TransObject)
+        group.name.should == "johnny"
+        group[:ensure].should == :present
+    end
+
+    it "should ignore tags and schedules when creating files and directories"
+
+    it "should apply all resources in debug mode to reduce logging"
+
+    it "should not try to manage absent files" do
+        # Make it think we're root so it tries to manage user and group.
+        Puppet.features.stubs(:root?).returns(true)
+        trans = nil
+        trans = @settings.to_transportable
+        file = nil
+        trans.delve { |obj| file = obj if obj.name == "/myfile" }
+        file.should be_nil
+    end
+
+    it "should not try to manage files in memory" do
+        main = Puppet::Type.type(:file).create(:path => "/maindir")
+
+        trans = @settings.to_transportable
+
+        lambda { trans.to_catalog }.should_not raise_error
+    end
+
+    it "should do nothing if a catalog cannot be created" do
+        bucket = mock 'bucket'
+        catalog = mock 'catalog'
+
+        @settings.expects(:to_transportable).returns bucket
+        bucket.expects(:to_catalog).raises RuntimeError
+        catalog.expects(:apply).never
+
+        @settings.use(:mysection)
+    end
+
+    it "should clear the catalog after applying" do
+        bucket = mock 'bucket'
+        catalog = mock 'catalog'
+
+        @settings.expects(:to_transportable).returns bucket
+        bucket.expects(:to_catalog).returns catalog
+        catalog.stubs(:host_config=)
+        catalog.stubs(:apply)
+        catalog.expects(:clear)
+
+        @settings.use(:mysection)
+    end
+
+    it "should clear the catalog even if there is an exception during applying" do
+        bucket = mock 'bucket'
+        catalog = mock 'catalog'
+
+        @settings.expects(:to_transportable).returns bucket
+        bucket.expects(:to_catalog).returns catalog
+        catalog.stubs(:host_config=)
+        catalog.expects(:apply).raises(ArgumentError)
+        catalog.expects(:clear)
+
+        # We don't care about the raised exception, we just care that
+        # we clear the catalog even with the exception
+        lambda { @settings.use(:mysection) }.should raise_error
+    end
+
+    it "should do nothing if all specified sections have already been used" do
+        bucket = mock 'bucket'
+        catalog = mock 'catalog'
+
+        @settings.expects(:to_transportable).once.returns(bucket)
+        bucket.expects(:to_catalog).returns catalog
+        catalog.stub_everything
+
+        @settings.use(:whatever)
+
+        @settings.use(:whatever)
+    end
+
+    it "should ignore file settings whose values are not strings" do
+        @settings[:maindir] = false
+
+        lambda { trans = @settings.to_transportable }.should_not raise_error
+    end
+
+    it "should be able to turn the current configuration into a parseable manifest"
+
+    it "should convert octal numbers correctly when producing a manifest"
+
+    it "should be able to provide all of its parameters in a format compatible with GetOpt::Long" do
+        pending "Not converted from test/unit yet"
+    end
+
+    it "should not attempt to manage files within /dev" do
+        pending "Not converted from test/unit yet"
+    end
+
+    it "should not modify the stored state database when managing resources" do
+        Puppet::Util::Storage.expects(:store).never
+        Puppet::Util::Storage.expects(:load).never
+        Dir.expects(:mkdir).with("/maindir")
+        Dir.expects(:mkdir).with("/seconddir")
+        @settings.use(:main)
+    end
+
+    it "should convert all relative paths to fully-qualified paths (#795)" do
+        @settings[:myfile] = "unqualified"
+        dir = Dir.getwd
+        @settings[:myfile].should == File.join(dir, "unqualified")
+    end
+
+    it "should support a method for re-using all currently used sections" do
+        Dir.expects(:mkdir).with("/thirddir").times(2)
+        @settings.use(:third)
+        @settings.reuse
+    end
+
+    it "should fail if any resources fail" do
+        stub_transaction
+        @trans.expects(:any_failed?).returns(true)
+
+        proc { @settings.use(:whatever) }.should raise_error(RuntimeError)
+    end
+
+    after { Puppet::Type.allclear }
+end
diff --git a/spec/unit/util/tagging.rb b/spec/unit/util/tagging.rb
new file mode 100755
index 0000000..d61ee8c
--- /dev/null
+++ b/spec/unit/util/tagging.rb
@@ -0,0 +1,92 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2008-01-19.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/util/tagging'
+
+describe Puppet::Util::Tagging, "when adding tags" do
+    before do
+        @tagger = Object.new
+        @tagger.extend(Puppet::Util::Tagging)
+    end
+
+    it "should have a method for adding tags" do
+        @tagger.should be_respond_to(:tag)
+    end
+
+    it "should have a method for returning all tags" do
+        @tagger.should be_respond_to(:tags)
+    end
+
+    it "should add tags to the returned tag list" do
+        @tagger.tag("one")
+        @tagger.tags.should be_include("one")
+    end
+
+    it "should not add duplicate tags to the returned tag list" do
+        @tagger.tag("one")
+        @tagger.tag("one")
+        @tagger.tags.should == ["one"]
+    end
+
+    it "should return a duplicate of the tag list, rather than the original" do
+        @tagger.tag("one")
+        tags = @tagger.tags
+        tags << "two"
+        @tagger.tags.should_not be_include("two")
+    end
+
+    it "should add all provided tags to the tag list" do
+        @tagger.tag("one", "two")
+        @tagger.tags.should be_include("one")
+        @tagger.tags.should be_include("two")
+    end
+
+    it "should fail on tags containing '*' characters" do
+        lambda { @tagger.tag("bad*tag") }.should raise_error(Puppet::ParseError)
+    end
+
+    it "should fail on tags starting with '-' characters" do
+        lambda { @tagger.tag("-badtag") }.should raise_error(Puppet::ParseError)
+    end
+
+    it "should fail on tags containing ' ' characters" do
+        lambda { @tagger.tag("bad tag") }.should raise_error(Puppet::ParseError)
+    end
+
+    it "should allow alpha tags" do
+        lambda { @tagger.tag("good_tag") }.should_not raise_error(Puppet::ParseError)
+    end
+
+    it "should allow tags containing '.' characters" do
+        lambda { @tagger.tag("good.tag") }.should_not raise_error(Puppet::ParseError)
+    end
+
+    it "should provide a method for testing tag validity" do
+        @tagger.metaclass.publicize_methods(:valid_tag?)  { @tagger.should be_respond_to(:valid_tag?) }
+    end
+
+    it "should add qualified classes as tags" do
+        @tagger.tag("one::two")
+        @tagger.tags.should be_include("one::two")
+    end
+
+    it "should add each part of qualified classes as tags" do
+        @tagger.tag("one::two::three")
+        @tagger.tags.should be_include("one")
+        @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/spec/unit/util/uri_helper.rb b/spec/unit/util/uri_helper.rb
new file mode 100755
index 0000000..f454a2c
--- /dev/null
+++ b/spec/unit/util/uri_helper.rb
@@ -0,0 +1,41 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2007-10-18.
+#  Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/util/uri_helper'
+
+describe Puppet::Util::URIHelper, " when converting a key to a URI" do
+    before do
+        @helper = Object.new
+        @helper.extend(Puppet::Util::URIHelper)
+    end
+
+    it "should return the URI instance" do
+        URI.expects(:parse).with("file:///myhost/blah").returns(:myuri)
+        @helper.key2uri("/myhost/blah").should == :myuri
+    end
+
+    it "should escape the key before parsing" do
+        URI.expects(:escape).with("mykey").returns("http://myhost/blah")
+        URI.expects(:parse).with("http://myhost/blah").returns(:myuri)
+        @helper.key2uri("mykey").should == :myuri
+    end
+
+    it "should use the URI class to parse the key" do
+        URI.expects(:parse).with("http://myhost/blah").returns(:myuri)
+        @helper.key2uri("http://myhost/blah").should == :myuri
+    end
+
+    it "should set the scheme to 'file' if the key is a fully qualified path" do
+        URI.expects(:parse).with("file:///myhost/blah").returns(:myuri)
+        @helper.key2uri("/myhost/blah").should == :myuri
+    end
+
+    it "should set the host to 'nil' if the key is a fully qualified path" do
+        URI.expects(:parse).with("file:///myhost/blah").returns(:myuri)
+        @helper.key2uri("/myhost/blah").should == :myuri
+    end
+end
diff --git a/test/certmgr/support.rb b/test/certmgr/support.rb
index 10d4319..cdbbe3f 100755
--- a/test/certmgr/support.rb
+++ b/test/certmgr/support.rb
@@ -78,32 +78,5 @@ class TestCertSupport < Test::Unit::TestCase
             @user.ca_cert
         end
     end
-
-    # Fixing #1382.  This test will always fail on Darwin, because its
-    # FS is case-insensitive.
-    unless Facter.value(:operatingsystem) == "Darwin"
-        def test_uppercase_files_are_renamed_and_read
-            # Write a key out to disk in a file containing upper-case.
-            key = OpenSSL::PKey::RSA.new(32)
-            should_path = Puppet[:hostprivkey]
-            puts "%s: %s" % [should_path, FileTest.exist?(should_path).inspect]
-
-            dir, file = File.split(should_path)
-            newfile = file.sub(/^([a-z.]+)\./) { $1.upcase + "."}
-            puts "%s: %s" % [should_path, FileTest.exist?(should_path).inspect]
-            upper_path = File.join(dir, newfile)
-            puts "%s: %s" % [should_path, FileTest.exist?(should_path).inspect]
-            puts "%s: %s" % [upper_path, FileTest.exist?(upper_path).inspect]
-            File.open(upper_path, "w") { |f| f.print key.to_s }
-            puts "%s: %s" % [should_path, FileTest.exist?(should_path).inspect]
-            puts "%s: %s" % [upper_path, FileTest.exist?(upper_path).inspect]
-
-            user = CertUser.new
-
-            assert_equal(key.to_s, user.read_key.to_s, "Did not read key in from disk")
-            assert(! FileTest.exist?(upper_path), "Upper case file was not removed")
-            assert(FileTest.exist?(should_path), "File was not renamed to lower-case file")
-            assert_equal(key.to_s, user.read_key.to_s, "Did not read key in from disk")
-        end
-    end
 end
+
diff --git a/test/data/providers/ssh_authorized_key/parsed/authorized_keys b/test/data/providers/ssh_authorized_key/parsed/authorized_keys
deleted file mode 100644
index 033f98b..0000000
--- a/test/data/providers/ssh_authorized_key/parsed/authorized_keys
+++ /dev/null
@@ -1,5 +0,0 @@
-ssh-dss AAAAB3NzaC1kc3MAAACBAJkupmdsJSDXfUy5EU5NTRBDr9Woo3w0YnB8KmnJW9ghU8C7SkWPB1fIHVe+esFfd3qWBseb83PoFX63geZJAg6bjV4/Rdn1zEoa9EO2QyUdYUen4+rpsh3vVKZ6HFNsn3+W5+kPYgE1F/N4INqkbjY3sqCkP/W1BL9+sbVVbuJFAAAAFQCfjWDk5XhvGUkPjNWWVqltBYzHtwAAAIEAg/XL7ky7x9Ad5banzPFAfmM+DGFe0A/JEbLDjKmr5KBM5x4RFohtEvZ8ECuVGUOqBWdgAjyYwsG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4knEl+mNfOLq+FH0011UhecOiqTcESMzQDtgQ1vJh2VchElBLjl3x/ZugAAACAAh5jGQC338t5ObP8trSlOefkx0sXmmEzUbo3Mt8mGUuGJPx8m+X0L8Xd+l5rQxytqE3SmV/RD+6REqBuPqHM8RQuqAzfjdOeg/Ajdggx1CRMTVhltZsgQoxO30cz9Qo0SdPoL+Jp1fLuaLZq7m/RmsWYvoLT3jebBlpvvQE8YlI= francois.deppierraz at nimag.net
-ssh-dss AAAAB3NzaC1kc3MAAACBAJkupmdsJSDXfUy5EU5NTRBDr9Woo3w0YnB8KmnJW9ghU8C7SkWPB1fIHVe+esFfd3qWBseb83PoFX63geZJAg6bjV4/Rdn1zEoa9EO2QyUdYUen4+rpsh3vVKZ6HFNsn3+W5+kPYgE1F/N4INqkbjY3sqCkP/W1BL9+sbVVbuJFAAAAFQCfjWDk5XhvGUkPjNWWVqltBYzHtwAAAIEAg/XL7ky7x9Ad5banzPFAfmM+DGFe0A/JEbLDjKmr5KBM5x4RFohtEvZ8ECuVGUOqBWdgAjyYwsG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4knEl+mNfOLq+FH0011UhecOiqTcESMzQDtgQ1vJh2VchElBLjl3x/ZugAAACAAh5jGQC338t5ObP8trSlOefkx0sXmmEzUbo3Mt8mGUuGJPx8m+X0L8Xd+l5rQxytqE3SmV/RD+6REqBuPqHM8RQuqAzfjdOeg/Ajdggx1CRMTVhltZsgQoxO30cz9Qo0SdPoL+Jp1fLuaLZq7m/RmsWYvoLT3jebBlpvvQE8YlI= Francois Deppierraz <francois at ctrlaltdel.ch>
-from="192.168.1.1",command="/bin/false",no-pty,no-port-forwarding ssh-dss AAAAB3NzaC1kc3MAAACBAJkupmdsJSDXfUy5EU5NTRBDr9Woo3w0YnB8KmnJW9ghU8C7SkWPB1fIHVe+esFfd3qWBseb83PoFX63geZJAg6bjV4/Rdn1zEoa9EO2QyUdYUen4+rpsh3vVKZ6HFNsn3+W5+kPYgE1F/N4INqkbjY3sqCkP/W1BL9+sbVVbuJFAAAAFQCfjWDk5XhvGUkPjNWWVqltBYzHtwAAAIEAg/XL7ky7x9Ad5banzPFAfmM+DGFe0A/JEbLDjKmr5KBM5x4RFohtEvZ8ECuVGUOqBWdgAjyYwsG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4knEl+mNfOLq+FH0011UhecOiqTcESMzQDtgQ1vJh2VchElBLjl3x/ZugAAACAAh5jGQC338t5ObP8trSlOefkx0sXmmEzUbo3Mt8mGUuGJPx8m+X0L8Xd+l5rQxytqE3SmV/RD+6REqBuPqHM8RQuqAzfjdOeg/Ajdggx1CRMTVhltZsgQoxO30cz9Qo0SdPoL+Jp1fLuaLZq7m/RmsWYvoLT3jebBlpvvQE8YlI= Francois Deppierraz
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2Vi+TdC3iOGYcIo5vGTvC9P9rjHl9RxCuZmSfn+YDFQ35RXf0waijtjp9I7GYh6R4hBjA5z0u/Pzi95LET5NfRM0Gdc0DJyvBI7K+ALBxIT383Iz6Yz4iKxe1TEJgHGM2he4+7BHkjc3kdIZqIpZjucCk4VsXSxujO4MKKvtaKK2l+kahlLQHHw/vZkDpIgL52iGVsjW9l8RLJaKHZ4mDHJN/Q/Rzn2W4EvcdHUzwhvGMwZlm8clDwITBrSsawYtnivJrQSYcmTRqJuS8wprNDrLIhTGjrwFg5WpruUuMt6fLuCqwe6TeEL+nh3DQ4g554c5aRp3oU6LGBKTvNZGWQ== francois at korn
-ssh-dss AAAAB3NzaC1kc3MAAACBAMPpCYnjywOemd8LqbbmC+bePNR3/H1rXsiFwjSLhYE3bbOpvclvOzN1DruFc34m0FopVnMkP+aubjdIYF8pijl+5hg9ggB7Kno2dl0Dd1rGN/swvmhA8OpLAQv7Qt7UnXKVho3as08zYZsrHxYFu0wlnkdbsv4cy4aXyQKd4MPVAAAAFQDSyQFWg8Qt3wU05buhZ10psoR7tQAAAIEAmAhguXwUnI3P2FF5NAW/mpJUmUERdL4pyZARUyAgpf7ezwrh9TJqrvGTQNBF97Xqaivyncm5JWQdMIsTBxEFaXZGkmBta02KnWcn447qvIh7iv8XpNL6M9flCkBEZOJ4t9El0ytTSHHaiCz8A20Et+E8evWyi1kXkFDt8ML2dGgAAACBAK0X4ympbdEjgV/ZyOc+BU22u7vOnfSOUJmyar4Ax1MIDNnoyNWKnGvxRutydQcQOKQHZEU0fE8MhPFn6nLF6CoVfEl/oz0EYz3hjV4WPFpHrF5DY/rhvNj8iuneKJ5P0dy/rG6m5qey25PnHyGFVoIRlkHJvBCJT40dHs40YEjI francois at korn
diff --git a/test/data/providers/ssh_authorized_key/parsed/authorized_keys1 b/test/data/providers/ssh_authorized_key/parsed/authorized_keys1
deleted file mode 100644
index 7aa0647..0000000
--- a/test/data/providers/ssh_authorized_key/parsed/authorized_keys1
+++ /dev/null
@@ -1,3 +0,0 @@
-1024 35 167576894966720957580065952882142495543043407324667405194097438434880798807651864847570827148390962746149410384891026772700627764845955493549511618975091512997118590589399665757714186775228807376424903966072778732134483862302766419277581465932186641863495699668069439475320990051723279127881281145164415361627 francois at korn
-2048 35 27332429396020032283276339339051507284036000350350092862949624519871013308460312287866673933080560923221560798334008554200019645416448528663000202951887890525621015333936122655294782671001073795264378070156670395703161543893088138531854776737799752600933431638059304355933305878665812555436198516842364330938321746086651639330436648850787370397302524667456837036413634152938122227368132322078811602953517461933179827432019932348409533535942749570969101453655028606209719023224268890314608444789012688070463327764203306501923404494017305972543000091038543051645924928018568725584728655193415567703220002707737714942757 francois at korn
-from="192.168.1.1",command="/bin/false",no-pty,no-port-forwarding 2048 35 27332429396020032283276339339051507284036000350350092862949624519871013308460312287866673933080560923221560798334008554200019645416448528663000202951887890525621015333936122655294782671001073795264378070156670395703161543893088138531854776737799752600933431638059304355933305878665812555436198516842364330938321746086651639330436648850787370397302524667456837036413634152938122227368132322078811602953517461933179827432019932348409533535942749570969101453655028606209719023224268890314608444789012688070463327764203306501923404494017305972543000091038543051645924928018568725584728655193415567703220002707737714942757 francois at korn
diff --git a/test/data/snippets/append.pp b/test/data/snippets/append.pp
deleted file mode 100644
index 28edeb1..0000000
--- a/test/data/snippets/append.pp
+++ /dev/null
@@ -1,11 +0,0 @@
-$var=['/tmp/file1','/tmp/file2']
-
-class arraytest {
-	$var += ['/tmp/file3', '/tmp/file4']
-	file {
-		$var:
-			content => "test"
-	}
-}
-
-include arraytest
diff --git a/test/data/snippets/arithmetic_expression.pp b/test/data/snippets/arithmetic_expression.pp
deleted file mode 100644
index aae98a4..0000000
--- a/test/data/snippets/arithmetic_expression.pp
+++ /dev/null
@@ -1,8 +0,0 @@
-
-$one = 1.30
-$two = 2.034e-2
-
-$result = ((( $two + 2) / $one) + 4 * 5.45) - (6 << 7) + (0x800 + -9)
-
-
-notice("result is $result == 1295.87692307692")
\ No newline at end of file
diff --git a/test/data/snippets/arraytrailingcomma.pp b/test/data/snippets/arraytrailingcomma.pp
deleted file mode 100644
index a410f95..0000000
--- a/test/data/snippets/arraytrailingcomma.pp
+++ /dev/null
@@ -1,3 +0,0 @@
-file {
-    ["/tmp/arraytrailingcomma1","/tmp/arraytrailingcomma2", ]: content => "tmp"
-}
diff --git a/test/data/snippets/emptyifelse.pp b/test/data/snippets/emptyifelse.pp
deleted file mode 100644
index 598b486..0000000
--- a/test/data/snippets/emptyifelse.pp
+++ /dev/null
@@ -1,9 +0,0 @@
-
-if false {
-} else {
-  # nothing here
-}
-
-if true {
-  # still nothing
-}
diff --git a/test/data/snippets/funccomma.pp b/test/data/snippets/funccomma.pp
deleted file mode 100644
index 32e34f9..0000000
--- a/test/data/snippets/funccomma.pp
+++ /dev/null
@@ -1,5 +0,0 @@
- at file {
-    ["/tmp/funccomma1","/tmp/funccomma2"]: content => "1"
-}
-
-realize( File["/tmp/funccomma1"], File["/tmp/funccomma2"] , )
diff --git a/test/data/snippets/ifexpression.rb b/test/data/snippets/ifexpression.rb
deleted file mode 100644
index eea3b85..0000000
--- a/test/data/snippets/ifexpression.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-$one = 1
-$two = 2
-
-if ($one < $two) and (($two < 3) or ($two == 2)) {
-    notice("True!")
-}
diff --git a/test/data/types/ssh_authorized_key/1 b/test/data/types/ssh_authorized_key/1
deleted file mode 100644
index 69d1af1..0000000
--- a/test/data/types/ssh_authorized_key/1
+++ /dev/null
@@ -1,2 +0,0 @@
-ssh-dss AAAAB3NzaC1kc3MAAACBAJkupmdsJSDXfUy5EU5NTRBDr9Woo3w0YnB8KmnJW9ghU8C7SkWPB1fIHVe+esFfd3qWBseb83PoFX63geZJAg6bjV4/Rdn1zEoa9EO2QyUdYUen4+rpsh3vVKZ6HFNsn3+W5+kPYgE1F/N4INqkbjY3sqCkP/W1BL9+sbVVbuJFAAAAFQCfjWDk5XhvGUkPjNWWVqltBYzHtwAAAIEAg/XL7ky7x9Ad5banzPFAfmM+DGFe0A/JEbLDjKmr5KBM5x4RFohtEvZ8ECuVGUOqBWdgAjyYwsG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4knEl+mNfOLq+FH0011UhecOiqTcESMzQDtgQ1vJh2VchElBLjl3x/ZugAAACAAh5jGQC338t5ObP8trSlOefkx0sXmmEzUbo3Mt8mGUuGJPx8m+X0L8Xd+l5rQxytqE3SmV/RD+6REqBuPqHM8RQuqAzfjdOeg/Ajdggx1CRMTVhltZsgQoxO30cz9Qo0SdPoL+Jp1fLuaLZq7m/RmsWYvoLT3jebBlpvvQE8YlI= francois.deppierraz at camptocamp.com
-from="192.168.1.2",command="/usr/local/bin/backup.sh",no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-rsa AAAAB3NzaC1kc3MAAACBAJkupmdsJSDXfUy5EU5NTRBDr9Woo3w0YnB8KmnJW9ghU8C7SkWPB1fIHVesG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4ksG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4ksG4oRVjLnKrf/rgmbNRzSFgEWkcAye3BVwk7Dt6hh4kxytqE3SmV/RD+6REqBuPqHM8RQuqAzfjdOeg/Ajdggx1CRMTVhltZsgQoxO30cz9Qo0SdPoL+Jp1fLuaL Backup system
diff --git a/test/language/ast/resource_reference.rb b/test/language/ast/resource_reference.rb
index 75cb53c..1f554d9 100755
--- a/test/language/ast/resource_reference.rb
+++ b/test/language/ast/resource_reference.rb
@@ -23,6 +23,34 @@ class TestASTResourceReference < Test::Unit::TestCase
         @parser = @scope.compiler.parser
     end
 
+    def test_evaluate
+        @parser.newdefine "one::two"
+        @parser.newdefine "one-two"
+        [%w{File /tmp/yay}, %w{One::Two three}, %w{One-two three}].each do |type, title|
+            ref = newref(type, title)
+
+            evaled = nil
+            assert_nothing_raised("Could not evaluate resource ref") do
+                evaled = ref.evaluate(@scope)
+            end
+
+            assert_equal(type, evaled.type, "Type did not translate correctly")
+            assert_equal(title, evaled.title, "Title did not translate correctly")
+        end
+    end
+
+    def test_finding_classes_for_reference
+        @parser.newclass "one"
+        ref = newref("Class", "one")
+        evaled = nil
+        assert_nothing_raised("Could not evaluate resource ref") do
+            evaled = ref.evaluate(@scope)
+        end
+
+        assert_equal("Class", evaled.type, "Did not set type to 'class'")
+        assert_equal("one", evaled.title, "Did not look up class corectly")
+    end
+
     # Related to #706, make sure resource references correctly translate to qualified types.
     def test_scoped_references
         @parser.newdefine "one"
diff --git a/test/language/functions.rb b/test/language/functions.rb
index d9a1a56..a5d52d7 100755
--- a/test/language/functions.rb
+++ b/test/language/functions.rb
@@ -96,12 +96,11 @@ class TestLangFunctions < Test::Unit::TestCase
         twop = File.join(Puppet[:templatedir], "two")
 
         File.open(onep, "w") do |f|
-            f.puts "<%- if @one.nil? then raise '@one undefined' end -%>" +
-                "template <%= @one %>"
+            f.puts "template <%= one %>"
         end
 
         File.open(twop, "w") do |f|
-            f.puts "template <%= @two %>"
+            f.puts "template <%= two %>"
         end
         func = nil
         assert_nothing_raised do
@@ -117,27 +116,15 @@ class TestLangFunctions < Test::Unit::TestCase
         ast = varobj("output", func)
 
         scope = mkscope
-
-        # Test that our manual exception throw fails the parse
         assert_raise(Puppet::ParseError) do
             ast.evaluate(scope)
         end
 
-        # Test that our use of an undefined instance variable does not throw
-        # an exception, but only safely continues.
         scope.setvar("one", "One")
-        assert_nothing_raised do
+        assert_raise(Puppet::ParseError) do
             ast.evaluate(scope)
         end
-
-        # Ensure that we got the output we expected from that evaluation.
-        assert_equal("template One\ntemplate \n", scope.lookupvar("output"),
-                     "Undefined template variables do not raise exceptions")
-
-        # Now, fill in the last variable and make sure the whole thing
-        # evaluates correctly.
         scope.setvar("two", "Two")
-        scope.unsetvar("output")
         assert_nothing_raised do
             ast.evaluate(scope)
         end
@@ -151,7 +138,7 @@ class TestLangFunctions < Test::Unit::TestCase
         template = tempfile()
 
         File.open(template, "w") do |f|
-            f.puts "template <%= @yay.nil?() ? raise('yay undefined') : @yay %>"
+            f.puts "template <%= yayness %>"
         end
 
         func = nil
@@ -171,77 +158,17 @@ class TestLangFunctions < Test::Unit::TestCase
             ast.evaluate(scope)
         end
 
-        scope.setvar("yay", "this is yay")
+        scope.setvar("yayness", "this is yayness")
 
         assert_nothing_raised do
             ast.evaluate(scope)
         end
 
-        assert_equal("template this is yay\n", scope.lookupvar("output"),
+        assert_equal("template this is yayness\n", scope.lookupvar("output"),
             "Templates were not handled correctly")
 
     end
 
-    # Make sure that legacy template variable access works as expected.
-    def test_legacyvariables
-        template = tempfile()
-
-        File.open(template, "w") do |f|
-            f.puts "template <%= deprecated %>"
-        end
-
-        func = nil
-        assert_nothing_raised do
-            func = Puppet::Parser::AST::Function.new(
-                :name => "template",
-                :ftype => :rvalue,
-                :arguments => AST::ASTArray.new(
-                    :children => [stringobj(template)]
-                )
-            )
-        end
-        ast = varobj("output", func)
-
-        # Verify that we get an exception using old-style accessors.
-        scope = mkscope
-        assert_raise(Puppet::ParseError) do
-            ast.evaluate(scope)
-        end
-
-        # Verify that we evaluate and return their value correctly.
-        scope.setvar("deprecated", "deprecated value")
-        assert_nothing_raised do
-            ast.evaluate(scope)
-        end
-
-        assert_equal("template deprecated value\n", scope.lookupvar("output"),
-                     "Deprecated template variables were not handled correctly")
-    end
-
-    # Make sure that problems with kernel method visibility still exist.
-    def test_kernel_module_shadows_deprecated_var_lookup
-        template = tempfile()
-        File.open(template, "w").puts("<%= binding %>")
-
-        func = nil
-        assert_nothing_raised do
-            func = Puppet::Parser::AST::Function.new(
-                :name => "template",
-                :ftype => :rvalue,
-                :arguments => AST::ASTArray.new(
-                    :children => [stringobj(template)]
-                )
-            )
-        end
-        ast = varobj("output", func)
-
-        # Verify that Kernel methods still shadow deprecated variable lookups.
-        scope = mkscope
-        assert_nothing_raised("No exception for Kernel shadowed variable names") do
-            ast.evaluate(scope)
-        end
-    end
-
     def test_tempatefunction_cannot_see_scopes
         template = tempfile()
 
@@ -278,7 +205,7 @@ class TestLangFunctions < Test::Unit::TestCase
         file = tempfile()
 
         Puppet[:code] = %{file { "#{file}": content => template("#{template}") }}
-        Puppet[:environment] = "yay"
+        Puppet[:environments] = "yay"
         interp = Puppet::Parser::Interpreter.new
         node = mknode
         node.stubs(:environment).returns("yay")
@@ -316,7 +243,7 @@ class TestLangFunctions < Test::Unit::TestCase
         template = tempfile()
 
         File.open(template, "w") do |f|
-            f.puts "template <%= @yayness %>"
+            f.puts "template <%= yayness %>"
         end
 
         func = nil
@@ -336,6 +263,10 @@ class TestLangFunctions < Test::Unit::TestCase
             false => "false",
         }.each do |string, value|
             scope = mkscope
+            assert_raise(Puppet::ParseError) do
+                ast.evaluate(scope)
+            end
+
             scope.setvar("yayness", string)
             assert_equal(string, scope.lookupvar("yayness", false))
 
@@ -379,8 +310,6 @@ class TestLangFunctions < Test::Unit::TestCase
         scope = mkscope
         parser = scope.compiler.parser
     
-        realize = Puppet::Parser::Functions.function(:realize)
-
         # Make a definition
         parser.newdefine("mytype")
         
@@ -436,8 +365,6 @@ class TestLangFunctions < Test::Unit::TestCase
     def test_defined
         scope = mkscope
         parser = scope.compiler.parser
-
-        defined = Puppet::Parser::Functions.function(:defined)
         
         parser.newclass("yayness")
         parser.newdefine("rahness")
@@ -495,8 +422,6 @@ class TestLangFunctions < Test::Unit::TestCase
         scope = mkscope
         parser = scope.compiler.parser
 
-        include = Puppet::Parser::Functions.function(:include)
-
         assert_raise(Puppet::ParseError, "did not throw error on missing class") do
             scope.function_include("nosuchclass")
         end
@@ -514,8 +439,6 @@ class TestLangFunctions < Test::Unit::TestCase
         parser = mkparser
         scope = mkscope(:parser => parser)
 
-        file = Puppet::Parser::Functions.function(:file)
-
         file1 = tempfile
         file2 = tempfile
         file3 = tempfile
@@ -556,8 +479,6 @@ class TestLangFunctions < Test::Unit::TestCase
         assert_equal("yay\n", %x{#{command}}, "command did not work")
         assert_equal("yay-foo\n", %x{#{command} foo}, "command did not work")
 
-        generate = Puppet::Parser::Functions.function(:generate)
-
         scope = mkscope
         parser = scope.compiler.parser
 
diff --git a/test/language/parser.rb b/test/language/parser.rb
index 2453bdf..cdd1329 100755
--- a/test/language/parser.rb
+++ b/test/language/parser.rb
@@ -66,19 +66,6 @@ class TestParser < Test::Unit::TestCase
         }
     end
 
-    def test_arrayrvalueswithtrailingcomma
-        parser = mkparser
-        ret = nil
-        file = tempfile()
-        assert_nothing_raised {
-            parser.string = "file { \"#{file}\": mode => [755, 640,] }"
-        }
-
-        assert_nothing_raised {
-            ret = parser.parse
-        }
-    end
-
     def mkmanifest(file)
         name = File.join(tmpdir, "file%s" % rand(100))
         @@tmpfiles << name
@@ -1221,13 +1208,5 @@ file { "/tmp/yayness":
             parser.import("test") 
         end
     end
-
-    def test_watch_file_only_once
-        FileTest.stubs(:exists?).returns(true)
-        parser = mkparser
-        parser.watch_file("doh")
-        parser.watch_file("doh")
-        assert_equal(1, parser.files.select { |name, file| file.file == "doh" }.length, "Length of watched 'doh' files was not 1")
-    end
 end
 
diff --git a/test/language/scope.rb b/test/language/scope.rb
index 0fa211f..c96581a 100755
--- a/test/language/scope.rb
+++ b/test/language/scope.rb
@@ -53,34 +53,6 @@ class TestScope < Test::Unit::TestCase
             assert_equal(:undefined, scopes[name].lookupvar("third", false), "Found child var in top scope")
         end
         assert_equal("botval", scopes[:bot].lookupvar("third", false), "Could not find var in bottom scope")
-
-
-        # Test that the scopes convert to hash structures correctly.
-        # For topscope recursive vs non-recursive should be identical
-        assert_equal(topscope.to_hash(false), topscope.to_hash(true),
-                     "Recursive and non-recursive hash is identical for topscope")
-
-        # Check the variable we expect is present.
-        assert_equal({"first" => "topval"}, topscope.to_hash(),
-                     "topscope returns the expected hash of variables")
-
-        # Now, check that midscope does the right thing in all cases.
-        assert_equal({"second" => "midval"},
-                     midscope.to_hash(false),
-                     "midscope non-recursive hash contains only midscope variable")
-        assert_equal({"first" => "topval", "second" => "midval"},
-                     midscope.to_hash(true),
-                     "midscope recursive hash contains topscope variable also")
-
-        # Finally, check the ability to shadow symbols by adding a shadow to
-        # bottomscope, then checking that we see the right stuff.
-        botscope.setvar("first", "shadowval")
-        assert_equal({"third" => "botval", "first" => "shadowval"},
-                     botscope.to_hash(false),
-                     "botscope has the right non-recursive hash")
-        assert_equal({"third" => "botval", "first" => "shadowval", "second" => "midval"},
-                     botscope.to_hash(true),
-                     "botscope values shadow parent scope values")
     end
 
     def test_lookupvar
diff --git a/test/language/snippets.rb b/test/language/snippets.rb
index ebc9773..982ddfe 100755
--- a/test/language/snippets.rb
+++ b/test/language/snippets.rb
@@ -446,20 +446,6 @@ class TestSnippets < Test::Unit::TestCase
             "Did not make second file from duplicate subclass names")
     end
 
-    def snippet_funccomma
-        assert_file("/tmp/funccomma1",
-            "Did not make first file from trailing function comma")
-        assert_file("/tmp/funccomma2",
-            "Did not make second file from trailing function comma")
-    end
-
-    def snippet_arraytrailingcomma
-        assert_file("/tmp/arraytrailingcomma1",
-            "Did not make first file from array")
-        assert_file("/tmp/arraytrailingcomma2",
-            "Did not make second file from array")
-    end
-
     # Iterate across each of the snippets and create a test.
     Dir.entries(snippetdir).sort.each { |file|
         next if file =~ /^\./
diff --git a/test/lib/puppettest/reporttesting.rb b/test/lib/puppettest/reporttesting.rb
index 4d88c3c..9b1764c 100644
--- a/test/lib/puppettest/reporttesting.rb
+++ b/test/lib/puppettest/reporttesting.rb
@@ -6,6 +6,8 @@ module PuppetTest::Reporttesting
         3.times { |i|
             # We have to use warning so that the logs always happen
             log = Puppet.warning("Report test message %s" % i)
+            log.tags = %w{a list of tags}
+            log.tags << "tag%s" % i
 
             report.newlog(log)
         }
diff --git a/test/lib/puppettest/runnable_test.rb b/test/lib/puppettest/runnable_test.rb
index 6dab1b7..e4b0f90 100644
--- a/test/lib/puppettest/runnable_test.rb
+++ b/test/lib/puppettest/runnable_test.rb
@@ -12,14 +12,9 @@ module PuppetTest
             end
         end
 
-        attr_reader :messages
-
         # Evaluate all of our tests to see if any of them are false
         # and thus whether this test is considered not runnable.
         def runnable?
-            if superclass.respond_to?(:runnable?) and ! superclass.runnable?
-                return false
-            end
             @messages ||= []
             return false unless @messages.empty?
             return true unless defined? @confines
diff --git a/test/lib/puppettest/support/utils.rb b/test/lib/puppettest/support/utils.rb
index 654531c..cb4a692 100644
--- a/test/lib/puppettest/support/utils.rb
+++ b/test/lib/puppettest/support/utils.rb
@@ -88,7 +88,7 @@ module PuppetTest::Support::Utils
         newevents = nil
         assert_nothing_raised("Transaction %s %s failed" % [type, msg]) {
             newevents = trans.send(method).reject { |e| e.nil? }.collect { |e|
-                e.name
+                e.event
             }
         }
 
diff --git a/test/lib/rake/puppet_testtask.rb b/test/lib/rake/puppet_testtask.rb
index a4b8d8b..6e8e364 100644
--- a/test/lib/rake/puppet_testtask.rb
+++ b/test/lib/rake/puppet_testtask.rb
@@ -1,8 +1,5 @@
 #!/usr/bin/env ruby
 
-require 'rake'
-require 'rake/testtask'
-
 module Rake
     class PuppetTestTask < Rake::TestTask
         def rake_loader
diff --git a/test/network/client/ca.rb b/test/network/client/ca.rb
index 56419b6..9781e95 100755
--- a/test/network/client/ca.rb
+++ b/test/network/client/ca.rb
@@ -30,7 +30,6 @@ class TestClientCA < Test::Unit::TestCase
 
     # Make sure the ca defaults to specific ports and names
     def test_ca_server
-        Puppet.settings.stubs(:value).returns "eh"
         Puppet.settings.expects(:value).with(:ca_server).returns("myca")
         Puppet.settings.expects(:value).with(:ca_port).returns(321)
         Puppet.settings.stubs(:value).with(:http_proxy_host).returns(nil)
diff --git a/test/network/client/master.rb b/test/network/client/master.rb
index 90f747d..dc2140e 100755
--- a/test/network/client/master.rb
+++ b/test/network/client/master.rb
@@ -177,12 +177,10 @@ end
 
         assert(File.exists?(destfile), "Did not get fact")
 
-        facts = Puppet::Network::Client.master.facts
-
-        assert_equal(hostname, facts["hostname"],
+        assert_equal(hostname, Facter.value(:hostname),
             "Lost value to hostname")
 
-        assert_equal("yayness", facts["myfact"],
+        assert_equal("yayness", Facter.value(:myfact),
             "Did not get correct fact value")
 
         # Now modify the file and make sure the type is replaced
@@ -196,22 +194,20 @@ end
         assert_nothing_raised {
             Puppet::Network::Client.master.getfacts
         }
-        facts = Puppet::Network::Client.master.facts
 
-        assert_equal("funtest", facts["myfact"],
+        assert_equal("funtest", Facter.value(:myfact),
             "Did not reload fact")
-        assert_equal(hostname, facts["hostname"],
+        assert_equal(hostname, Facter.value(:hostname),
             "Lost value to hostname")
 
         # Now run it again and make sure the fact still loads
         assert_nothing_raised {
             Puppet::Network::Client.master.getfacts
         }
-        facts = Puppet::Network::Client.master.facts
 
-        assert_equal("funtest", facts["myfact"],
+        assert_equal("funtest", Facter.value(:myfact),
             "Did not reload fact")
-        assert_equal(hostname, facts["hostname"],
+        assert_equal(hostname, Facter.value(:hostname),
             "Lost value to hostname")
     end
 
@@ -402,9 +398,12 @@ end
             client.send(:splay)
         end
 
+        time = Puppet::Util::Storage.cache(:configuration)[:splay_time]
+        assert(time, "Splay time was not cached")
+
         # Now try it again
         client = mkclient
-        client.expects(:sleep)
+        client.expects(:sleep).with(time)
 
         assert_nothing_raised("Failed to call sleep when splay is true with a cached value") do
             client.send(:splay)
@@ -416,7 +415,8 @@ end
         assert_equal(facts["environment"], Puppet[:environment], "Did not add environment to client facts")
 
         # Now set it to a real value
-	Puppet[:environment] = "something"
+        Puppet[:environments] = "something,else"
+        Puppet[:environment] = "something"
         facts = Puppet::Network::Client::Master.facts
         assert_equal(facts["environment"], Puppet[:environment], "Did not add environment to client facts")
     end
@@ -472,8 +472,17 @@ end
 
         Puppet::Node::Facts.indirection.stubs(:save)
 
-        master = Puppet::Network::Handler.master.new( :Local => false)
-        client = Puppet::Network::Client.master.new( :Master => master)
+        master = client = nil
+        assert_nothing_raised() {
+            master = Puppet::Network::Handler.master.new(
+                :Local => false
+            )
+        }
+        assert_nothing_raised() {
+            client = Puppet::Network::Client.master.new(
+                :Master => master
+            )
+        }
 
         # Fake that it's local, so it creates the class file
         client.local = false
@@ -482,7 +491,6 @@ end
         client.expects(:setclasses).with do |array|
             array.length == 2 and array.include?("yaytest") and array.include?("bootest")
         end
-
         assert_nothing_raised {
             client.getconfig
         }
diff --git a/test/network/handler/fileserver.rb b/test/network/handler/fileserver.rb
index 873657e..a705dbf 100755
--- a/test/network/handler/fileserver.rb
+++ b/test/network/handler/fileserver.rb
@@ -437,14 +437,6 @@ class TestFileServer < Test::Unit::TestCase
         assert_nil(retval, "Description of non-existent mounts returned a value")
     end
 
-    def test_describe_does_not_fail_when_mount_does_not_find_file
-        server = Puppet::Network::Handler.fileserver.new(:Local => true, :Config => false)
-
-        assert_nothing_raised("Failed when describing missing plugins") do
-            server.describe "/plugins"
-        end
-    end
-
     # test that our config file is parsing and working as planned
     def test_configfile
         server = nil
diff --git a/test/network/handler/master.rb b/test/network/handler/master.rb
index 654404a..e91ec2f 100755
--- a/test/network/handler/master.rb
+++ b/test/network/handler/master.rb
@@ -8,87 +8,69 @@ require 'puppet/network/handler/master'
 class TestMaster < Test::Unit::TestCase
     include PuppetTest::ServerTest
 
-    def setup
-        super
-        @master = Puppet::Network::Handler.master.new(:Manifest => tempfile)
-
-        @catalog = stub 'catalog', :extract => ""
-        Puppet::Node::Catalog.stubs(:find).returns(@catalog)
-    end
-
     def teardown
         super
         Puppet::Indirector::Indirection.clear_cache
     end
 
     def test_freshness_is_always_now
+        master = Puppet::Network::Handler.master.new(
+            :Manifest => tempfile,
+            :UseNodes => true,
+            :Local => true
+        )
+
         now1 = mock 'now1'
         Time.expects(:now).returns(now1)
 
-        now1.expects(:to_i).returns 10
-
-        assert_equal(@master.freshness, 10, "Did not return current time as freshness")
+        assert_equal(master.freshness, now1, "Did not return current time as freshness")
     end
 
-    def test_hostname_is_used_if_client_is_missing
-        @master.expects(:decode_facts).returns("hostname" => "yay")
-        Puppet::Node::Facts.expects(:new).with { |name, facts| name == "yay" }.returns(stub('facts', :save => nil))
-
-        @master.getconfig("facts")
-    end
-
-    def test_facts_are_saved
-        facts = mock('facts')
-        Puppet::Node::Facts.expects(:new).returns(facts)
-        facts.expects(:save)
-
-        @master.stubs(:decode_facts)
-
-        @master.getconfig("facts", "yaml", "foo.com")
-    end
-
-    def test_catalog_is_used_for_compiling
-        facts = stub('facts', :save => nil)
-        Puppet::Node::Facts.stubs(:new).returns(facts)
-
-        @master.stubs(:decode_facts)
-
-        Puppet::Node::Catalog.expects(:find).with("foo.com").returns(@catalog)
-
-        @master.getconfig("facts", "yaml", "foo.com")
+    # Make sure we're correctly doing clientname manipulations.
+    # Testing to make sure we always get a hostname and IP address.
+    def test_clientname
+        # create our master
+        master = Puppet::Network::Handler.master.new(
+            :Manifest => tempfile,
+            :UseNodes => true,
+            :Local => true
+        )
+
+
+        # First check that 'cert' works
+        Puppet[:node_name] = "cert"
+
+        # Make sure we get the fact data back when nothing is set
+        facts = {
+            "hostname" => "fact_hostname",
+            "domain" => "fact_domain",
+            "fqdn" => "fact_hostname.fact_domain",
+            "ipaddress" => "fact_ip"
+        }
+        certhostname = "cert_hostname"
+        certdomain = "cert_domain"
+        certname = certhostname + "." + certdomain
+        certip = "cert_ip"
+
+        resname, resip = master.send(:clientname, nil, nil, facts)
+        assert_equal(facts["hostname"], resname, "Did not use fact hostname when no certname was present")
+        assert_equal(facts["ipaddress"], resip, "Did not use fact ip when no certname was present")
+        assert_equal(facts["domain"], "fact_domain", "Did not use fact domain when no certname was present")
+        assert_equal(facts["fqdn"], "fact_hostname.fact_domain", "Did not use fact fqdn when no certname was present")
+
+        # Now try it with the cert stuff present
+        resname, resip = master.send(:clientname, certname, certip, facts)
+        assert_equal(certname, resname, "Did not use cert hostname when certname was present")
+        assert_equal(certip, resip, "Did not use cert ip when certname was present")
+        assert_equal(facts["domain"], certdomain, "Did not use cert domain when certname was present")
+        assert_equal(facts["fqdn"], certname, "Did not use cert fqdn when certname was present")
+
+        # And reset the node_name stuff and make sure we use it.
+        Puppet[:node_name] = :facter
+        resname, resip = master.send(:clientname, certname, certip, facts)
+        assert_equal(facts["hostname"], resname, "Did not use fact hostname when nodename was set to facter")
+        assert_equal(facts["ipaddress"], resip, "Did not use fact ip when nodename was set to facter")
     end
 end
 
-class TestMasterFormats < Test::Unit::TestCase
-    def setup
-        @facts = stub('facts', :save => nil)
-        Puppet::Node::Facts.stubs(:new).returns(@facts)
-
-        @master = Puppet::Network::Handler.master.new(:Code => "")
-        @master.stubs(:decode_facts)
-
-        @catalog = stub 'catalog', :extract => ""
-        Puppet::Node::Catalog.stubs(:find).returns(@catalog)
-    end
-
-    def test_marshal_can_be_used
-        @catalog.expects(:extract).returns "myextract"
-
-        Marshal.expects(:dump).with("myextract").returns "eh"
-
-        @master.getconfig("facts", "marshal", "foo.com")
-    end
-
-    def test_yaml_can_be_used
-        extract = mock 'extract'
-        @catalog.expects(:extract).returns extract
 
-        extract.expects(:to_yaml).returns "myaml"
-
-        @master.getconfig("facts", "yaml", "foo.com")
-    end
-
-    def test_failure_when_non_yaml_or_marshal_is_used
-        assert_raise(RuntimeError) { @master.getconfig("facts", "blah", "foo.com") }
-    end
-end
diff --git a/test/other/propertychange.rb b/test/other/propertychange.rb
new file mode 100755
index 0000000..eaa4f40
--- /dev/null
+++ b/test/other/propertychange.rb
@@ -0,0 +1,140 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke A. Kanies on 2006-12-21.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../lib/puppettest'
+
+require 'puppettest'
+
+class TestPropertyChange < Test::Unit::TestCase
+	include PuppetTest
+	class FakeProperty < Puppet::Property
+	    attr_accessor :is, :should, :resource
+	    attr_reader :noop
+	    def change_to_s(currentvalue, newvalue)
+	        "fake change"
+        end
+	    def insync?(is)
+	        is == @should
+        end
+        def log(msg)
+            Puppet::Util::Log.create(
+                :level => :info,
+                :source => self,
+                :message => msg
+            )
+        end
+        def noop
+            if defined? @noop
+                @noop
+            else
+                false
+            end
+        end
+        def path
+            "fakechange"
+        end
+        def should_to_s(newvalue)
+            newvalue.to_s
+        end
+        def sync
+            if insync?(@is)
+                return nil
+            else
+                @is = @should
+                return :fake_change
+            end
+        end
+        def to_s
+            path
+        end
+    end
+    
+    def mkchange
+        property = FakeProperty.new :resource => "fakeparent"
+        property.is = :start
+        property.should = :finish
+        property.resource = :parent
+        change = nil
+        assert_nothing_raised do
+            change = Puppet::PropertyChange.new(property, :start)
+        end
+        change.transaction = :trans
+        
+        assert_equal(:start, change.is, "@is did not get copied")
+        assert_equal(:finish, change.should, "@should did not get copied")
+        assert_equal(%w{fakechange change}, change.path, "path did not get set correctly")
+        
+        assert(! change.changed?, "change defaulted to already changed")
+        
+        return change
+    end
+    
+	def test_go
+	    change = mkchange
+	    
+	    coll = logcollector()
+	    
+	    events = nil
+	    # First make sure we get an immediate return 
+	    assert_nothing_raised do
+    	    events = change.go
+	    end
+	    assert_instance_of(Array, events, "events were not returned in an array")
+	    assert_instance_of(Puppet::Event, events[0], "event array did not contain events")
+
+	    event = events.shift
+	    {:event => :fake_change, :transaction => :trans, :source => :parent}.each do |method, val|
+	        assert_equal(val, event.send(method), "Event did not set %s correctly" % method)
+        end
+	    
+        # Disabled, because it fails when running the whole suite at once.
+        #assert(coll.detect { |l| l.message == "fake change" }, "Did not log change")
+	    assert_equal(change.property.is, change.property.should, "did not call sync method")
+	    
+	    # Now make sure that proxy sources can be set.
+	    assert_nothing_raised do
+    	    change.proxy = :other
+	    end
+	    # Reset, so we change again
+	    change.property.is = :start
+	    change.is = :start
+	    assert_nothing_raised do
+	        events = change.go
+        end
+        
+	    assert_instance_of(Array, events, "events were not returned in an array")
+	    assert_instance_of(Puppet::Event, events[0], "event array did not contain events")
+
+	    event = events.shift
+	    {:event => :fake_change, :transaction => :trans, :source => :other}.each do |method, val|
+	        assert_equal(val, event.send(method), "Event did not set %s correctly" % method)
+        end
+	    
+	    #assert(coll.detect { |l| l.message == "fake change" }, "Did not log change")
+	    assert_equal(change.property.is, change.property.should, "did not call sync method")
+    end
+
+    # Related to #542.  Make sure changes in noop mode produce the :noop event.
+    def test_noop_event
+        change = mkchange
+
+        assert(! change.skip?, "Change is already being skipped")
+
+        Puppet[:noop] = true
+
+        change.property.noop = true
+        assert(change.noop, "did not set noop")
+        assert(change.skip?, "setting noop did not mark change for skipping")
+
+        event = nil
+        assert_nothing_raised("Could not generate noop event") do
+            event = change.forward
+        end
+
+        assert_equal(1, event.length, "got wrong number of events")
+        assert_equal(:noop, event[0].event, "did not generate noop mode when in noop")
+    end
+end
+
diff --git a/test/other/provider.rb b/test/other/provider.rb
index b0860f6..3e4ad83 100755
--- a/test/other/provider.rb
+++ b/test/other/provider.rb
@@ -48,6 +48,51 @@ class TestImpl < Test::Unit::TestCase
 
     end
 
+    def test_provider_false_confine
+        assert_nothing_raised do
+            @provider.confine :false => false
+        end
+
+        assert(@provider.suitable?, "False did not check correctly")
+    end
+
+    def test_provider_true_confine
+        assert_nothing_raised do
+            @provider.confine :true => true
+        end
+
+        assert(@provider.suitable?, "True did not check correctly")
+
+        # Now check whether we multiple true things work
+        assert_nothing_raised do
+            @provider.confine :true => false
+            @provider.confine :true => true
+        end
+        assert(! @provider.suitable?, "One truth overrode another")
+    end
+
+    def test_provider_exists_confine
+        file = tempfile()
+
+        assert_nothing_raised do
+            @provider.confine :exists => file
+        end
+
+        assert(! @provider.suitable?, "Exists did not check correctly")
+        File.open(file, "w") { |f| f.puts "" }
+        assert(@provider.suitable?, "Exists did not find file correctly")
+    end
+
+    def test_provider_facts_confine
+        # Now check for multiple platforms
+        assert_nothing_raised do
+            @provider.confine :operatingsystem => [Facter["operatingsystem"].value, :yayos]
+            @provider.confine :operatingsystem => [:fakeos, :otheros]
+        end
+
+        assert(@provider.suitable?, "Implementation not considered suitable")
+    end
+
     def test_provider_default
         nondef = nil
         assert_nothing_raised {
diff --git a/test/other/report.rb b/test/other/report.rb
index 9d0bb48..9894e2a 100755
--- a/test/other/report.rb
+++ b/test/other/report.rb
@@ -21,7 +21,7 @@ class TestReports < Test::Unit::TestCase
             # Make every third file
             File.open(file, "w") { |f| f.puts "" } if i % 3 == 0
 
-            objects << Puppet::Type.type(:file).create(
+            objects << Puppet::Type.newfile(
                 :path => file,
                 :ensure => "file"
             )
@@ -44,7 +44,7 @@ class TestReports < Test::Unit::TestCase
         }
 
         # Now make a file for testing logging
-        file = Puppet::Type.type(:file).create(:path => tempfile(), :ensure => "file")
+        file = Puppet::Type.newfile(:path => tempfile(), :ensure => "file")
         file.finish
 
         log = nil
@@ -91,6 +91,8 @@ class TestReports < Test::Unit::TestCase
 
         3.times { |i|
             log = Puppet.warning("Report test message %s" % i)
+            log.tags = %w{a list of tags}
+            log.tags << "tag%s" % i
 
             report.newlog(log)
         }
diff --git a/test/other/transactions.rb b/test/other/transactions.rb
index b1dbaed..ce2d0d5 100755
--- a/test/other/transactions.rb
+++ b/test/other/transactions.rb
@@ -72,11 +72,11 @@ class TestTransactions < Test::Unit::TestCase
         path1 = tempfile()
         path2 = tempfile()
         objects = []
-        objects << Puppet::Type.type(:file).create(
+        objects << Puppet::Type.newfile(
             :path => path1,
             :content => "yayness"
         )
-        objects << Puppet::Type.type(:file).create(
+        objects << Puppet::Type.newfile(
             :path => path2,
             :content => "booness"
         )
@@ -155,7 +155,7 @@ class TestTransactions < Test::Unit::TestCase
         path = tempfile()
         firstpath = tempfile()
         secondpath = tempfile()
-        file = Puppet::Type.type(:file).create(:title => "file", :path => path, :content => "yayness")
+        file = Puppet::Type.newfile(:title => "file", :path => path, :content => "yayness")
         first = Puppet::Type.newexec(:title => "first",
                                      :command => "/bin/echo first > #{firstpath}",
                                      :subscribe => [:file, path],
@@ -248,7 +248,7 @@ class TestTransactions < Test::Unit::TestCase
 
         assert_nothing_raised() {
             check.each { |property|
-                value = file.property(property).retrieve
+                value = file.value(property)
                 assert(value)
                 properties[property] = value
             }
@@ -716,45 +716,6 @@ class TestTransactions < Test::Unit::TestCase
             "Not all resources were evaluated or not in the right order")
     end
 
-    # We need to generate resources before we prefetch them, else generated
-    # resources that require prefetching don't work.
-    def test_generate_before_prefetch
-        config = mk_catalog()
-        trans = Puppet::Transaction.new(config)
-
-        generate = nil
-        prefetch = nil
-        trans.expects(:generate).with { |*args| generate = Time.now; true }
-        trans.expects(:prefetch).with { |*args| ! generate.nil? }
-        trans.prepare
-        return
-
-        resource = Puppet::Type.type(:file).create :ensure => :present, :path => tempfile()
-        other_resource = mock 'generated'
-        def resource.generate
-            [other_resource]
-        end
-
-
-        config = mk_catalog(yay, rah)
-        trans = Puppet::Transaction.new(config)
-        
-        assert_nothing_raised do
-            trans.generate
-        end
-        
-        %w{ya ra y r}.each do |name|
-            assert(trans.catalog.vertex?(Puppet::Type.type(:generator)[name]),
-                "Generated %s was not a vertex" % name)
-            assert($finished.include?(name), "%s was not finished" % name)
-        end
-        
-        # Now make sure that cleanup gets rid of those generated types.
-        assert_nothing_raised do
-            trans.cleanup
-        end
-    end
-
     def test_ignore_tags?
         config = Puppet::Node::Catalog.new
         config.host_config = true
@@ -796,7 +757,7 @@ class TestTransactions < Test::Unit::TestCase
     def test_proxy_resources
         type = mkreducer do
             def evaluate
-                return Puppet::Transaction::Change.new(Fakeprop.new(
+                return Puppet::PropertyChange.new(Fakeprop.new(
                     :path => :path, :is => :is, :should => :should, :name => self.name, :resource => "a parent"), :is)
             end
         end
@@ -815,7 +776,7 @@ class TestTransactions < Test::Unit::TestCase
         assert(changes.length > 0, "did not get any changes")
         
         changes.each do |change|
-            assert_equal(resource, change.resource, "change did not get proxy set correctly")
+            assert_equal(resource, change.source, "change did not get proxy set correctly")
         end
     end
     
@@ -905,16 +866,17 @@ class TestTransactions < Test::Unit::TestCase
         assert(result, "c did not trigger anything")
         assert_instance_of(Array, result)
         event = result.shift
-        assert_instance_of(Puppet::Transaction::Event, event)
-        assert_equal(:triggered, event.name, "event was not set correctly")
+        assert_instance_of(Puppet::Event, event)
+        assert_equal(:triggered, event.event, "event was not set correctly")
         assert_equal(c, event.source, "source was not set correctly")
+        assert_equal(trans, event.transaction, "transaction was not set correctly")
 
         assert(trans.triggered?(c, :refresh),
             "Transaction did not store the trigger")
     end
     
     def test_set_target
-        file = Puppet::Type.type(:file).create(:path => tempfile(), :content => "yay")
+        file = Puppet::Type.newfile(:path => tempfile(), :content => "yay")
         exec1 = Puppet::Type.type(:exec).create :command => "/bin/echo exec1"
         exec2 = Puppet::Type.type(:exec).create :command => "/bin/echo exec2"
         trans = Puppet::Transaction.new(mk_catalog(file, exec1, exec2))
@@ -949,7 +911,7 @@ class TestTransactions < Test::Unit::TestCase
             Puppet::Type.rmtype(:norefresh)
         end
 
-        file = Puppet::Type.type(:file).create :path => tempfile(), :content => "yay"
+        file = Puppet::Type.newfile :path => tempfile(), :content => "yay"
         one = klass.create :name => "one", :subscribe => file
         
         assert_apply(file, one)
@@ -994,7 +956,7 @@ class TestTransactions < Test::Unit::TestCase
             newparam(:name) {}
             newproperty(:testing) do
                 def sync
-                    # noop
+                    self.is = self.should
                     :ran_testing
                 end
             end
@@ -1027,8 +989,8 @@ class TestTransactions < Test::Unit::TestCase
         # Now files
         d = tempfile()
         f = File.join(d, "file")
-        file = Puppet::Type.type(:file).create(:path => f, :content => "yay")
-        dir = Puppet::Type.type(:file).create(:path => d, :ensure => :directory, :require => file)
+        file = Puppet::Type.newfile(:path => f, :content => "yay")
+        dir = Puppet::Type.newfile(:path => d, :ensure => :directory, :require => file)
         
         rels[dir] = file
         rels.each do |after, before|
@@ -1052,7 +1014,7 @@ class TestTransactions < Test::Unit::TestCase
         path = tempfile
         epath = tempfile
         spath = tempfile
-        file = Puppet::Type.type(:file).create(:path => path, :ensure => :file,
+        file = Puppet::Type.newfile(:path => path, :ensure => :file,
             :title => "file")
         exec = Puppet::Type.type(:exec).create(:command => "touch %s" % epath,
             :path => ENV["PATH"], :subscribe => file, :refreshonly => true,
@@ -1090,7 +1052,7 @@ class TestTransactions < Test::Unit::TestCase
         3.times do |i|
             path = tempfile
             paths << path
-            file = Puppet::Type.type(:file).create(:path => path, :ensure => :absent,
+            file = Puppet::Type.newfile(:path => path, :ensure => :absent,
                 :backup => false, :title => "file%s" % i)
             File.open(path, "w") { |f| f.puts "" }
             files << file
diff --git a/test/ral/providers/cron/crontab.rb b/test/ral/providers/cron/crontab.rb
index d9f4602..53bd76c 100755
--- a/test/ral/providers/cron/crontab.rb
+++ b/test/ral/providers/cron/crontab.rb
@@ -530,6 +530,8 @@ class TestCronParsedProvider < Test::Unit::TestCase
             @provider.initvars
             str += "\n"
             target.write(str)
+            assert_equal(str, target.read,
+                "Did not write correctly")
             assert_nothing_raised("Could not prefetch with %s" % str.inspect) do
                 @provider.prefetch
             end
@@ -549,11 +551,6 @@ class TestCronParsedProvider < Test::Unit::TestCase
         end
     end
 
-    # #707
-    def test_write_freebsd_special
-        assert_equal(@provider.to_line(:record_type => :crontab, :ensure => :present, :special => "reboot", :command => "/bin/echo something"), "@reboot /bin/echo something")
-    end
-
     def test_prefetch
         cron = @type.create :command => "/bin/echo yay", :name => "test", :hour => 4
 
@@ -602,31 +599,5 @@ class TestCronParsedProvider < Test::Unit::TestCase
         result = target.read
         assert_equal("# Puppet Name: test\n* 4 * * * /bin/echo yay\n", result, "Did not write out environment setting")
     end
-
-    # Testing #1216
-    def test_strange_lines
-        @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram))
-        text = " 5 \t\t 1,2 * 1 0 /bin/echo funtest"
-
-        records = nil
-        assert_nothing_raised {
-            records = @provider.parse(text)
-        }
-
-        should = {
-            :minute => %w{5},
-            :hour => %w{1 2},
-            :monthday => :absent,
-            :month => %w{1},
-            :weekday => %w{0},
-            :command => "/bin/echo funtest"
-        }
-
-        is = records.shift
-        assert(is, "Did not get record")
-
-        should.each do |p, v|
-            assert_equal(v, is[p], "did not parse %s correctly" % p)
-        end
-    end
 end
+
diff --git a/test/ral/providers/group.rb b/test/ral/providers/group.rb
index 6479b4a..18b0866 100755
--- a/test/ral/providers/group.rb
+++ b/test/ral/providers/group.rb
@@ -30,18 +30,14 @@ class TestGroupProvider < Test::Unit::TestCase
     end
 
     def mkgroup(name, hash = {})
-        fakeresource = stub 'group', :allowdupe? => false, :name => name
-        fakeresource.stubs(:[]).returns nil
-        fakeresource.stubs(:should).returns nil
-        fakeresource.stubs(:[]).with(:name).returns name
-        hash.each do |name, val|
-            fakeresource.stubs(:should).with(name).returns val
-            fakeresource.stubs(:[]).with(name).returns val
-        end
+        fakeresource = fakeresource(:group, name)
         group = nil
         assert_nothing_raised {
             group = @provider.new(fakeresource)
         }
+        hash.each do |name, val|
+            fakeresource[name] = val
+        end
         assert(group, "Could not create provider group")
 
         return group
@@ -112,19 +108,19 @@ class TestGroupProvider < Test::Unit::TestCase
     def attrtest_ensure(group)
         old = group.ensure
         assert_nothing_raised {
-            group.delete
+            group.ensure = :absent
         }
 
         assert(!group.exists?, "Group was not deleted")
 
         assert_nothing_raised {
-            group.create
+            group.ensure = :present
         }
         assert(group.exists?, "Group was not created")
 
         unless old == :present
             assert_nothing_raised {
-                group.delete
+                group.ensure = old
             }
         end
     end
@@ -215,6 +211,7 @@ class TestGroupProvider < Test::Unit::TestCase
         unless Facter["operatingsystem"].value == "FreeBSD"
         def test_duplicateIDs
             group1 = mkgroup("group1", :gid => 125)
+            group2 = mkgroup("group2", :gid => 125)
 
             @@tmpgroups << "group1"
             @@tmpgroups << "group2"
@@ -225,14 +222,16 @@ class TestGroupProvider < Test::Unit::TestCase
 
             # Not all OSes fail here, so we can't test that it doesn't work with
             # it off, only that it does work with it on.
-            group2 = mkgroup("group2", :gid => 125)
-            group2.resource.stubs(:allowdupe?).returns true
+            assert_nothing_raised {
+                group2.resource[:allowdupe] = :true
+            }
 
             # Now create the second group
             assert_nothing_raised {
                 group2.create
             }
-            assert_equal(:present, group2.ensure, "Group did not get created")
+            assert_equal(:present, group2.ensure,
+                         "Group did not get created")
         end
         end
     else
diff --git a/test/ral/providers/package.rb b/test/ral/providers/package.rb
index 3b61c1a..f2d28d0 100755
--- a/test/ral/providers/package.rb
+++ b/test/ral/providers/package.rb
@@ -244,5 +244,36 @@ class TestPackageProvider < Test::Unit::TestCase
             pkg[:adminfile] = "/usr/local/pkg/admin_file"
         end
     end
+
+    # Make sure providers throw an error when you tell them to install a
+    # non-existent package.
+    def test_no_such_package
+        Puppet::Type.type(:package).suitableprovider.each do |provider|
+            assert_raise(ArgumentError, Puppet::Error, Puppet::ExecutionFailure,
+                "Successfully installed nonexistent package with %s" % provider.name) {
+                pkg = Puppet::Type.newpackage :name => "nosuch%s" % provider.name.to_s,
+                    :provider => provider.name
+                provider = pkg.provider
+                provider.install
+            }
+        end
+    end
+
+    # Make sure all of the suitable providers on our platform can successfully
+    # list.
+    def test_instances
+        Puppet::Type.type(:package).suitableprovider.each do |provider|
+            result = nil
+            assert_nothing_raised("Could not list %s packages" % provider.name) do
+                result = provider.instances
+            end
+            result.each do |pkg|
+                assert_instance_of(provider, pkg,
+                    "%s returned non-provider" % provider.name)
+                assert_equal(provider.name, pkg.class.name,
+                    "Provider %s returned an instance of a different provider" %  provider.name)
+            end
+        end
+    end
 end
 
diff --git a/test/ral/providers/package/apt.rb b/test/ral/providers/package/apt.rb
new file mode 100755
index 0000000..f4fb1a9
--- /dev/null
+++ b/test/ral/providers/package/apt.rb
@@ -0,0 +1,169 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../lib/puppettest'
+
+require 'mocha'
+
+class AptPackageProviderTest < PuppetTest::TestCase
+    confine "Apt package provider missing" =>
+        Puppet::Type.type(:package).provider(:apt).suitable?
+
+	def setup
+        super
+		@type = Puppet::Type.type(:package)
+	end
+	
+	def test_install
+		pkg = @type.create :name => 'faff',
+		                   :provider => :apt,
+		                   :ensure => :present,
+		                   :source => "/tmp/faff.deb"
+
+		pkg.provider.expects(
+		                 :dpkgquery
+					  ).with(
+							  '-W',
+							  '--showformat',
+							  '${Status} ${Package} ${Version}\n',
+							  'faff'
+					  ).returns(
+					        "deinstall ok config-files faff 1.2.3-1\n"
+					  ).times(1)
+
+		pkg.provider.expects(
+		                 :aptget
+		           ).with(
+		                 '-q',
+		                 '-y',
+		                 '-o',
+		                 'DPkg::Options::=--force-confold',
+		                 :install,
+		                 'faff'
+					  ).returns(0)
+		
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
+	end
+	
+	def test_purge
+		pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :purged
+
+		pkg.provider.expects(
+		                 :dpkgquery
+					  ).with(
+					        '-W',
+					        '--showformat',
+					        '${Status} ${Package} ${Version}\n',
+					        'faff'
+					  ).returns(
+					        "install ok installed faff 1.2.3-1\n"
+					  ).times(1)
+		pkg.provider.expects(
+		                 :aptget
+					  ).with(
+					        '-y',
+					        '-q',
+					        'remove',
+					        '--purge',
+					        'faff'
+					  ).returns(0)
+		pkg.provider.expects(
+		                 :dpkg
+					  ).with(
+					        '--purge',
+					        'faff'
+					  ).returns(0)
+		
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
+	end
+
+	def test_dont_try_to_purge_if_already_purged
+		pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :purged
+
+		pkg.provider.expects(
+		                 :dpkgquery
+					  ).with(
+					        '-W',
+					        '--showformat',
+					        '${Status} ${Package} ${Version}\n',
+					        'faff'
+					  ).raises(
+					        Puppet::ExecutionFailure,
+					        "No packages found matching faff.\n"
+					  ).times(1)
+		pkg.provider.expects(
+		                 :aptget
+					  ).never
+		
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
+	end
+
+	def test_dont_try_to_purge_if_already_purged_and_we_want_it_absent
+		pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :absent
+
+		pkg.provider.expects(
+		                 :dpkgquery
+					  ).with(
+					        '-W',
+					        '--showformat',
+					        '${Status} ${Package} ${Version}\n',
+					        'faff'
+					  ).raises(
+					        Puppet::ExecutionFailure,
+					        "No packages found matching faff.\n"
+					  ).times(1)
+		pkg.provider.expects(
+		                 :aptget
+					  ).never
+
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
+	end
+
+	def test_make_sure_we_purge_if_package_still_has_conffiles
+		pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :purged
+
+		pkg.provider.expects(
+		                 :dpkgquery
+					  ).with(
+					        '-W',
+					        '--showformat',
+					        '${Status} ${Package} ${Version}\n',
+					        'faff'
+					  ).returns(
+					        "deinstall ok config-files faff 1.2.3-1\n"
+					  ).times(1)
+		pkg.provider.expects(
+		                 :aptget
+					  ).with(
+					        '-y',
+					        '-q',
+					        'remove',
+					        '--purge',
+					        'faff'
+					  ).returns(0)
+		pkg.provider.expects(
+		                 :dpkg
+					  ).with(
+					        '--purge',
+					        'faff'
+					  ).returns(0)
+		
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
+	end
+	
+
+    def test_latest
+		pkg = @type.create :name => 'base-files', :provider => :apt
+
+        assert(pkg, "did not create pkg")
+        status = pkg.provider.query
+        assert(status, "base-files is not installed")
+        assert(status[:ensure] != :absent, "base-files is not installed")
+
+        latest = nil
+        assert_nothing_raised("Could not call latest") do
+            latest = pkg.provider.latest
+        end
+        assert(latest, "Could not get latest value from apt")
+    end
+end
+
diff --git a/test/ral/providers/package/aptitude.rb b/test/ral/providers/package/aptitude.rb
index 881f540..f8edceb 100755
--- a/test/ral/providers/package/aptitude.rb
+++ b/test/ral/providers/package/aptitude.rb
@@ -41,6 +41,7 @@ class AptitudePackageProviderTest < PuppetTest::TestCase
 					  ).returns(0)
 		
 		pkg.evaluate.each { |state| 
+                    state.transaction = self 
                     state.forward 
           }
 	end
@@ -66,6 +67,6 @@ class AptitudePackageProviderTest < PuppetTest::TestCase
 					        'faff'
 					  ).returns(0)
 		
-		pkg.evaluate.each { |state| state.forward }
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
 	end
 end
diff --git a/test/ral/providers/package/aptrpm.rb b/test/ral/providers/package/aptrpm.rb
index 32e0ea6..c005ee5 100755
--- a/test/ral/providers/package/aptrpm.rb
+++ b/test/ral/providers/package/aptrpm.rb
@@ -39,7 +39,7 @@ class AptrpmPackageProviderTest < PuppetTest::TestCase
                          'faff'
                     ).returns(0)
         
-        pkg.evaluate.each { |state| state.forward }
+        pkg.evaluate.each { |state| state.transaction = self; state.forward }
     end
     
     def test_uninstall
@@ -66,7 +66,7 @@ class AptrpmPackageProviderTest < PuppetTest::TestCase
                         'faff'
                     ).returns(0)
         
-        pkg.evaluate.each { |state| state.forward }
+        pkg.evaluate.each { |state| state.transaction = self; state.forward }
     end
 
     # LAK: I don't know where this test will ever return true..
diff --git a/test/ral/providers/package/dpkg.rb b/test/ral/providers/package/dpkg.rb
new file mode 100755
index 0000000..7e44275
--- /dev/null
+++ b/test/ral/providers/package/dpkg.rb
@@ -0,0 +1,64 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../lib/puppettest'
+
+require 'mocha'
+
+class DpkgPackageProviderTest < PuppetTest::TestCase
+    confine "dpkg package provider missing" =>
+        Puppet::Type.type(:package).provider(:dpkg).suitable?
+	def setup
+        super
+		@type = Puppet::Type.type(:package)
+	end
+	
+	def test_install
+		pkg = @type.create :name => 'faff',
+		                   :provider => :dpkg,
+		                   :ensure => :present,
+		                   :source => "/tmp/faff.deb"
+
+		pkg.provider.expects(
+		                 :dpkgquery
+					  ).with(
+							  '-W',
+							  '--showformat',
+							  '${Status} ${Package} ${Version}\n',
+							  'faff'
+					  ).returns(
+					        "deinstall ok config-files faff 1.2.3-1\n"
+					  ).times(1)
+
+		pkg.provider.expects(
+		                 :dpkg
+		           ).with(
+		                 '-i',
+		                 '/tmp/faff.deb'
+					  ).returns(0)
+		
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
+	end
+	
+	def test_purge
+		pkg = @type.create :name => 'faff', :provider => :dpkg, :ensure => :purged
+
+		pkg.provider.expects(
+		                 :dpkgquery
+					  ).with(
+					        '-W',
+					        '--showformat',
+					        '${Status} ${Package} ${Version}\n',
+					        'faff'
+					  ).returns(
+					        "install ok installed faff 1.2.3-1\n"
+					  ).times(1)
+		pkg.provider.expects(
+		                 :dpkg
+					  ).with(
+					        '--purge',
+					        'faff'
+					  ).returns(0)
+		
+		pkg.evaluate.each { |state| state.transaction = self; state.forward }
+	end
+end
diff --git a/test/ral/providers/provider.rb b/test/ral/providers/provider.rb
index 70f606a..2196faf 100755
--- a/test/ral/providers/provider.rb
+++ b/test/ral/providers/provider.rb
@@ -37,13 +37,12 @@ class TestProvider < Test::Unit::TestCase
         cleanup { Puppet::Type.rmtype(:provider_test) }
     end
 
-    def test_confine_defaults_to_suitable
-
+    def test_confine
         provider = newprovider
-        assert(provider.suitable?, "Marked unsuitable with no confines")
-    end
 
-    def test_confine_results
+        assert(provider.suitable?,
+            "Marked unsuitable with no confines")
+
         {
             {:true => true} => true,
             {:true => false} => false,
@@ -55,8 +54,6 @@ class TestProvider < Test::Unit::TestCase
             {:exists => echo} => true,
             {:exists => "/this/file/does/not/exist"} => false,
         }.each do |hash, result|
-            provider = newprovider
-
             # First test :true
             hash.each do |test, val|
                 assert_nothing_raised do
@@ -64,25 +61,19 @@ class TestProvider < Test::Unit::TestCase
                 end
             end
 
-            assert_equal(result, provider.suitable?, "Failed for %s" % [hash.inspect])
+            assert_equal(result, provider.suitable?,
+                "Failed for %s" % [hash.inspect])
 
             provider.initvars
         end
-    end
-
-    def test_multiple_confines_do_not_override
-        provider = newprovider
 
         # Make sure multiple confines don't overwrite each other
         provider.confine :true => false
         assert(! provider.suitable?)
         provider.confine :true => true
         assert(! provider.suitable?)
-    end
 
-    def test_one_failed_confine_is_sufficient
-
-        provider = newprovider
+        provider.initvars
 
         # Make sure we test multiple of them, and that a single false wins
         provider.confine :true => true, :false => false
@@ -91,18 +82,6 @@ class TestProvider < Test::Unit::TestCase
         assert(! provider.suitable?)
     end
 
-    # #1197 - the binary should not be
-    def test_command_checks_for_binaries_each_time
-        provider = newprovider
-
-        provider.commands :testing => "/no/such/path"
-
-        provider.stubs(:binary).returns "/no/such/path"
-
-        provider.command(:testing)
-        assert_equal("/no/such/path", provider.command(:testing), "Did not return correct binary path")
-    end
-
     def test_command
         {:echo => "echo", :echo_with_path => echo, :missing => "nosuchcommand", :missing_qualified => "/path/to/nosuchcommand"}.each do |name, command|
             provider = newprovider
diff --git a/test/ral/providers/user.rb b/test/ral/providers/user.rb
index 4df8958..0651d6c 100755
--- a/test/ral/providers/user.rb
+++ b/test/ral/providers/user.rb
@@ -214,20 +214,20 @@ class TestUserProvider < Test::Unit::TestCase
     def attrtest_ensure(user)
         old = user.ensure
         assert_nothing_raised {
-            user.delete
+            user.ensure = :absent
         }
 
         assert(missing?(user.name), "User is still present")
         assert_nothing_raised {
-            user.create
+            user.ensure = :present
         }
         assert(!missing?(user.name), "User is absent")
         assert_nothing_raised {
-            user.delete
+            user.ensure = :absent
         }
 
         unless old == :absent
-            user.create
+            user.ensure = old
         end
     end
 
@@ -398,10 +398,10 @@ class TestUserProvider < Test::Unit::TestCase
 
         # Some tests to verify that groups work correctly startig from nothing
         # Remove our user
-        user.delete
+        user.ensure = :absent
 
         # And add it again
-        user.create
+        user.ensure = :present
 
         # Make sure that the group list is added at creation time.
         # This is necessary because we don't have default fakedata for groups.
@@ -498,8 +498,8 @@ class TestUserProvider < Test::Unit::TestCase
             user2.resource[:uid] = 125
 
             cleanup do
-                user1.delete
-                user2.delete
+                user1.ensure = :absent
+                user2.ensure = :absent
             end
 
             # Not all OSes fail here, so we can't test that it doesn't work with
diff --git a/test/ral/type/filesources.rb b/test/ral/type/filesources.rb
index 24bc0b9..a7bb6fe 100755
--- a/test/ral/type/filesources.rb
+++ b/test/ral/type/filesources.rb
@@ -145,7 +145,16 @@ class TestFileSources < Test::Unit::TestCase
         # Make sure the munge didn't actually change the source
         assert_equal([source], property.should, "munging changed the source")
         
+        # First try it with a missing source
         currentvalue = nil
+        assert_nothing_raised do
+            currentvalue = property.retrieve
+        end
+        
+        # And make sure the property considers itself in sync, since there's nothing
+        # to do
+        assert(property.insync?(currentvalue), "source thinks there's work to do with no file or dest")
+        
         # Now make the dest a directory, and make sure the object sets :ensure
         # up to create a directory
         Dir.mkdir(source)
@@ -161,6 +170,9 @@ class TestFileSources < Test::Unit::TestCase
         
         # Now remove the source, and make sure :ensure was not modified
         Dir.rmdir(source)
+        assert_nothing_raised do
+            property.retrieve
+        end
         assert_equal(:directory, file.should(:ensure),
             "Did not keep :ensure setting")
         
@@ -196,6 +208,10 @@ class TestFileSources < Test::Unit::TestCase
         property = file.property(:source)
         assert(property, "did not get source property")
         
+        # Try it with no source at all
+        currentvalues = file.retrieve
+        assert(property.insync?(currentvalues[property]), "source property not in sync with missing source")
+
         # with a directory
         Dir.mkdir(source)
         currentvalues = file.retrieve
@@ -292,9 +308,11 @@ class TestFileSources < Test::Unit::TestCase
         # Lastly, make sure we return an empty array when no sources are there
         obj[:source] = [nosource, tempfile()]
         
-        assert_raise(Puppet::Error) do
+        assert_nothing_raised do
             result, sourced = obj.sourcerecurse(true)
         end
+        assert_equal([], sourced, "Did not get correct list of sourced objects")
+        assert_equal([], result, "Sourcerecurse failed when all sources are missing")
     end
 
     def test_simplelocalsource
@@ -605,9 +623,9 @@ class TestFileSources < Test::Unit::TestCase
             :name => name
         )
 
-        assert_raise Puppet::Error do 
+        assert_nothing_raised {
             file.retrieve
-        end 
+        }
 
         comp = mk_catalog(file)
         comp.apply
diff --git a/test/ral/type/mailalias.rb b/test/ral/type/mailalias.rb
index 6370223..ff1dd56 100755
--- a/test/ral/type/mailalias.rb
+++ b/test/ral/type/mailalias.rb
@@ -34,11 +34,12 @@ class TestMailAlias < Test::Unit::TestCase
     # This isn't much of a test, but then, it's not much of a type.
     def test_recipient_arrays
         resource = @type.create(:name => "luke", :recipient => "yay", :target => tempfile)
+        resource.provider.expects(:recipient).returns([:absent])
         values = nil
         assert_nothing_raised("Could not retrieve mailalias") do
             values = resource.retrieve.inject({}) { |hash, a| hash[a[0].name] = a[1]; hash }
         end
-        assert_equal(:absent, values[:recipient])
+        assert_equal([:absent], values[:recipient])
         resource.property(:recipient).expects(:set).with(%w{yay})
         assert_nothing_raised("Could not sync mailalias") do
             resource.property(:recipient).sync
diff --git a/test/ral/type/sshkey.rb b/test/ral/type/sshkey.rb
index 1656b5d..b9aed20 100755
--- a/test/ral/type/sshkey.rb
+++ b/test/ral/type/sshkey.rb
@@ -3,6 +3,7 @@
 require File.dirname(__FILE__) + '/../../lib/puppettest'
 
 require 'puppettest'
+require 'puppet/type/sshkey'
 require 'facter'
 
 class TestSSHKey < Test::Unit::TestCase
diff --git a/test/ral/type/user.rb b/test/ral/type/user.rb
index 4c8a9f9..87d5b60 100755
--- a/test/ral/type/user.rb
+++ b/test/ral/type/user.rb
@@ -164,6 +164,56 @@ class TestUser < Test::Unit::TestCase
         assert_equal(old, user.provider.shell, "Shell was not reverted")
     end
 
+    def attrtest_gid(user)
+        obj = nil
+        old = user.provider.gid
+        comp = mk_catalog("gidtest", user)
+
+        user.retrieve
+
+        user[:gid] = old
+
+        trans = assert_events([], comp, "user")
+
+        newgid = %w{nogroup nobody staff users daemon}.find { |gid|
+                begin
+                    group = Etc.getgrnam(gid)
+                rescue ArgumentError => detail
+                    next
+                end
+                old != group.gid and group.gid > 0
+        }
+
+        unless newgid
+            $stderr.puts "Cannot find alternate group; skipping gid test"
+            return
+        end
+
+        # first test by name
+        assert_nothing_raised("Failed to specify group by name") {
+            user[:gid] = newgid
+        }
+
+        trans = assert_events([:user_changed], comp, "user")
+
+        # then by id
+        newgid = Etc.getgrnam(newgid).gid
+
+        assert_nothing_raised("Failed to specify group by id for %s" % newgid) {
+            user[:gid] = newgid
+        }
+
+        user.retrieve
+
+        assert_events([], comp, "user")
+
+        assert_equal(newgid, user.provider.gid, "GID was not changed")
+
+        assert_rollback_events(trans, [:user_changed], "user")
+
+        assert_equal(old, user.provider.gid, "GID was not reverted")
+    end
+
     def attrtest_uid(user)
         obj = nil
         comp = mk_catalog("uidtest", user)
diff --git a/test/ral/type/yumrepo.rb b/test/ral/type/yumrepo.rb
index 21865e6..899a021 100755
--- a/test/ral/type/yumrepo.rb
+++ b/test/ral/type/yumrepo.rb
@@ -47,10 +47,7 @@ class TestYumRepo < Test::Unit::TestCase
             :enabled => "1",
             :gpgcheck => "1",
             :includepkgs => "absent",
-            :gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora",
-            :proxy => "http://proxy.example.com:80/",
-            :proxy_username => "username",
-            :proxy_password => "password"
+            :gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora"
         }
         repo = make_repo("base", values)
 
@@ -104,9 +101,6 @@ baseurl=http://example.com/yum/$releasever/$basearch/os/
 enabled=1
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora
-proxy=http://proxy.example.com:80/
-proxy_username=username
-proxy_password=password
 EOF
 
 end        
diff --git a/test/util/loadedfile.rb b/test/util/loadedfile.rb
new file mode 100755
index 0000000..fb64046
--- /dev/null
+++ b/test/util/loadedfile.rb
@@ -0,0 +1,121 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../lib/puppettest'
+
+require 'puppet'
+require 'puppet/util/loadedfile'
+require 'puppettest'
+
+class TestLoadedFile < Test::Unit::TestCase
+	include PuppetTest
+    def test_file
+        Puppet[:filetimeout] = 0
+        file = nil
+        path = tempfile()
+        File.open(path, "w") { |f| f.puts "yayness" }
+        assert_nothing_raised {
+            file = Puppet::Util::LoadedFile.new(path)
+        }
+
+        assert(!file.changed?, "File incorrectly returned changed")
+
+        File.open(path, "w") { |f| f.puts "booness" }
+        #file.tstamp = File.stat(path).ctime - 5
+        new = File.stat(path).ctime - 5
+        file.tstamp = new
+
+        assert(file.changed?, "File did not catch change")
+    end
+
+    def test_timeout
+        Puppet[:filetimeout] = 50
+        path = tempfile()
+
+        File.open(path, "w") { |f| f.puts "yay" }
+        file = nil
+        assert_nothing_raised {
+            file = Puppet::Util::LoadedFile.new(path)
+        }
+
+        assert_nothing_raised {
+            assert(!file.changed?,
+                "File thought it changed immediately")
+        }
+
+        sleep 1
+        File.open(path, "w") { |f| f.puts "yay" }
+        #file.tstamp = File.stat(path).ctime - 5
+
+        assert(!file.changed?,
+            "File was marked as changed too soon")
+
+        Puppet[:filetimeout] = 0
+        assert(file.changed?,
+            "File was not marked as changed soon enough")
+    end
+
+    def test_stamp
+        file = tempfile()
+        File.open(file, "w") { |f| f.puts "" }
+        obj = nil
+        assert_nothing_raised {
+            obj = Puppet::Util::LoadedFile.new(file)
+        }
+
+        # Make sure we don't refresh
+        Puppet[:filetimeout] = 50
+
+        stamp = File.stat(file).ctime
+
+        assert_equal(stamp, obj.stamp)
+
+        sleep 1
+        # Now change the file, and make sure the stamp doesn't update yet
+        File.open(file, "w") { |f| f.puts "" }
+        assert_equal(stamp, obj.stamp,
+            "File prematurely refreshed")
+
+        Puppet[:filetimeout] = 0
+        assert_equal(File.stat(file).ctime, obj.stamp,
+            "File did not refresh")
+    end
+
+    # Testing #394.
+    def test_changed_missing_file
+        file = tempfile()
+        File.open(file, "w") { |f| f.puts "" }
+        obj = nil
+        assert_nothing_raised {
+            obj = Puppet::Util::LoadedFile.new(file)
+        }
+        Puppet[:filetimeout] = -10
+
+        assert_nothing_raised {
+            obj.changed?
+        }
+
+        # Now remove the file
+        File.unlink(file)
+
+        assert_nothing_raised("removed file threw an error") {
+            assert(obj.changed?, "File was not considered changed when missing")
+        }
+    end
+
+    # Make sure negative values always result in change notifications.
+    def test_negative_always_changes
+        file = tempfile()
+        File.open(file, "w") { |f| f.puts "" }
+        obj = nil
+        assert_nothing_raised {
+            obj = Puppet::Util::LoadedFile.new(file)
+        }
+
+        assert(! obj.changed?, "file with no change considered changed")
+        # Now set a negative value
+        Puppet[:filetimeout] = -1
+
+        assert(obj.changed?, "negative file timeout did not disable checking")
+    end
+end
+
diff --git a/test/util/log.rb b/test/util/log.rb
index 8c7703c..523652f 100755
--- a/test/util/log.rb
+++ b/test/util/log.rb
@@ -114,6 +114,44 @@ class TestLog < Test::Unit::TestCase
         assert(FileTest.file?(file))
     end
 
+    def test_logtags
+        path = tempfile
+        File.open(path, "w") { |f| f.puts "yayness" }
+
+        file = Puppet.type(:file).create(
+            :path => path,
+            :check => [:owner, :group, :mode, :checksum],
+            :ensure => :file
+        )
+        file.tags = %w{this is a test}
+
+        property = file.property(:ensure)
+        assert(property, "Did not get property")
+        log = nil
+        assert_nothing_raised {
+            log = Puppet::Util::Log.new(
+                :level => :info,
+                :source => property,
+                :message => "A test message"
+            )
+        }
+
+        # Now yaml and de-yaml it, and test again
+        yamllog = YAML.load(YAML.dump(log))
+
+        {:log => log, :yaml => yamllog}.each do |type, msg|
+            assert(msg.tags, "Got no tags")
+
+            msg.tags.each do |tag|
+                assert(msg.tagged?(tag), "Was not tagged with %s" % tag)
+            end
+
+            assert_equal(msg.tags, property.tags, "Tags were not equal")
+            assert_equal(msg.source, property.path, "Source was not set correctly")
+        end
+
+    end
+
     # Verify that we can pass strings that match printf args
     def test_percentlogs
         Puppet::Util::Log.newdestination :syslog
@@ -144,6 +182,27 @@ class TestLog < Test::Unit::TestCase
         assert_instance_of(String, msg.source)
     end
 
+    # Verify that loglevel behaves as one expects
+    def test_loglevel
+        path = tempfile()
+        file = Puppet.type(:file).create(
+            :path => path,
+            :ensure => "file"
+        )
+
+        assert_nothing_raised {
+            assert_equal(:notice, file[:loglevel])
+        }
+
+        assert_nothing_raised {
+            file[:loglevel] = "warning"
+        }
+
+        assert_nothing_raised {
+            assert_equal(:warning, file[:loglevel])
+        }
+    end
+
     def test_destination_matching
         dest = nil
         assert_nothing_raised {
diff --git a/test/util/posixtest.rb b/test/util/posixtest.rb
new file mode 100755
index 0000000..34d68e3
--- /dev/null
+++ b/test/util/posixtest.rb
@@ -0,0 +1,169 @@
+#!/usr/bin/env ruby
+#
+#  Created by Luke Kanies on 2006-11-07.
+#  Copyright (c) 2006. All rights reserved.
+
+require File.dirname(__FILE__) + '/../lib/puppettest'
+
+require 'puppettest'
+require 'puppet/util/posix'
+
+class TestPosixUtil < Test::Unit::TestCase
+	include PuppetTest
+	include Puppet::Util::POSIX
+	
+	def mk_posix_resource(type, obj)
+	    field = idfield(type)
+        res = Puppet::Type.type(type).create(
+            :name => obj.name,
+            field => obj.send(field)
+        )
+        res.setdefaults
+        res
+    end
+	
+	def test_get_posix_field
+	    {:group => nonrootgroup, :passwd => nonrootuser}.each do |space, obj|
+            id = Puppet::Util.idfield(space)
+	        [obj.name, obj.send(id), obj.send(id).to_s].each do |test|
+        	    value = nil
+        	    assert_nothing_raised do
+        	        value = get_posix_field(space, :name, test)
+        	    end
+        	    assert_equal(obj.name, value, "did not get correct value from get_posix_field")
+    	    end
+	    end
+    end
+    
+    def test_get_provider_value
+        user = nonrootuser
+        obj = mk_posix_resource(:user, user)
+        
+        assert_nothing_raised do
+            assert_equal(user.uid, get_provider_value(:user, :uid, user.uid))
+            assert_equal(user.name, get_provider_value(:user, :name, user.name))
+        end
+    end
+    
+    def test_gid_and_uid
+        {:user => nonrootuser, :group => nonrootgroup}.each do |type, obj|
+            method = idfield(type)
+            # First make sure we get it back with both name and id with no object
+            [obj.name, obj.send(method)].each do |value|
+                assert_equal(obj.send(method), send(method, value))
+            end
+            
+            # Now make a Puppet resource and make sure we get it from that.
+            resource = mk_posix_resource(type, obj)
+            
+            [obj.name, obj.send(method)].each do |value|
+                assert_equal(obj.send(method), send(method, value))
+            end
+        end
+    end
+    
+    def test_util_methods
+        assert(Puppet::Util.respond_to?(:uid), "util does not have methods")
+    end
+    
+    # First verify we can convert a known user
+    def test_gidbyname
+        %x{groups}.split(" ").each { |group|
+            gid = nil
+            assert_nothing_raised {
+                gid = Puppet::Util.gid(group)
+            }
+
+            assert(gid, "Could not retrieve gid for %s" % group)
+        }
+    end
+
+    # Then verify we can retrieve a known group by gid
+    def test_gidbyid
+        %x{groups}.split(" ").each { |group|
+            obj = Puppet.type(:group).create(
+                :name => group,
+                :check => [:gid]
+            )
+            obj.setdefaults
+            current = obj.retrieve
+            id = nil
+            current.find { |prop, value| id = value if prop.name == :gid }
+            gid = nil
+            assert_nothing_raised {
+                gid = Puppet::Util.gid(id)
+            }
+
+            assert(gid, "Could not retrieve gid for %s" % group)
+            assert_equal(id, gid, "Got mismatched ids")
+        }
+    end
+
+    # Finally, verify that we can find groups by id even if we don't
+    # know them
+    def test_gidbyunknownid
+        gid = nil
+        group = Puppet::Util::SUIDManager.gid
+        assert_nothing_raised {
+            gid = Puppet::Util.gid(group)
+        }
+
+        assert(gid, "Could not retrieve gid for %s" % group)
+        assert_equal(group, gid, "Got mismatched ids")
+    end
+
+    def user
+        require 'etc'
+        unless defined? @user
+            obj = Etc.getpwuid(Puppet::Util::SUIDManager.uid)
+            @user = obj.name
+        end
+        return @user
+    end
+
+    # And do it all over again for users
+    # First verify we can convert a known user
+    def test_uidbyname
+        user = user()
+        uid = nil
+        assert_nothing_raised {
+            uid = Puppet::Util.uid(user)
+        }
+
+        assert(uid, "Could not retrieve uid for %s" % user)
+        assert_equal(Puppet::Util::SUIDManager.uid, uid, "UIDs did not match")
+    end
+
+    # Then verify we can retrieve a known user by uid
+    def test_uidbyid
+        user = user()
+        obj = Puppet.type(:user).create(
+            :name => user,
+            :check => [:uid]
+        )
+        obj.setdefaults
+        obj.retrieve
+        id = obj.provider.uid
+        uid = nil
+        assert_nothing_raised {
+            uid = Puppet::Util.uid(id)
+        }
+
+        assert(uid, "Could not retrieve uid for %s" % user)
+        assert_equal(id, uid, "Got mismatched ids")
+    end
+
+    # Finally, verify that we can find users by id even if we don't
+    # know them
+    def test_uidbyunknownid
+        uid = nil
+        user = Puppet::Util::SUIDManager.uid
+        assert_nothing_raised {
+            uid = Puppet::Util.uid(user)
+        }
+
+        assert(uid, "Could not retrieve uid for %s" % user)
+        assert_equal(user, uid, "Got mismatched ids")
+    end
+end
+
diff --git a/vendor/gems/mocha-0.5.6/._RELEASE b/vendor/gems/mocha-0.5.6/._RELEASE
new file mode 100644
index 0000000..12bf79c
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/._RELEASE differ
diff --git a/vendor/gems/mocha-0.5.6/._Rakefile b/vendor/gems/mocha-0.5.6/._Rakefile
new file mode 100644
index 0000000..22220c1
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/._Rakefile differ
diff --git a/vendor/gems/mocha-0.5.6/COPYING b/vendor/gems/mocha-0.5.6/COPYING
new file mode 100644
index 0000000..8f74d71
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/COPYING
@@ -0,0 +1,3 @@
+Copyright Revieworld Ltd. 2006
+
+You may use, copy and redistribute this library under the same terms as Ruby itself (see http://www.ruby-lang.org/en/LICENSE.txt) or under the MIT license (see MIT-LICENSE file).
diff --git a/vendor/gems/mocha-0.5.6/MIT-LICENSE b/vendor/gems/mocha-0.5.6/MIT-LICENSE
new file mode 100644
index 0000000..fa4efe7
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/MIT-LICENSE
@@ -0,0 +1,7 @@
+Copyright (c) 2006 Revieworld Ltd.
+
+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.
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/README b/vendor/gems/mocha-0.5.6/README
new file mode 100644
index 0000000..262c6ec
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/README
@@ -0,0 +1,35 @@
+= Mocha
+
+Mocha is a library for mocking and stubbing using a syntax like that of JMock[http://www.jmock.org], and SchMock[http://rubyforge.org/projects/schmock]. Most commonly Mocha is used in conjunction with Test::Unit[http://www.ruby-doc.org/core/classes/Test/Unit.html], but it can be used in other contexts.
+
+One of its main advantages is that it allows you to mock and stub methods on _real_ (non-mock) classes and instances. You can for example stub ActiveRecord[http://api.rubyonrails.com/classes/ActiveRecord/Base.html] instance methods like +create+, +save+, +destroy+ and even class methods like +find+ to avoid hitting the database in unit tests.
+
+Mocha provides a unified, simple and readable syntax for both traditional mocking and for mocking with _real_ objects.
+
+Mocha has been harvested from projects at Reevoo[http://www.reevoo.com] by me (James[http://blog.floehopper.org]) and my colleagues Ben[http://www.reevoo.com/blogs/bengriffiths], Chris[http://blog.seagul.co.uk] and Paul[http://po-ru.com]. Mocha is in use on real-world Rails[http://www.rubyonrails.org] projects.
+
+== Download and Installation
+
+Install the gem with the following command...
+
+  $ gem install mocha
+ 
+Or install the Rails[http://www.rubyonrails.org] plugin...
+
+  $ script/plugin install svn://rubyforge.org/var/svn/mocha/trunk
+
+Or download Mocha from here - http://rubyforge.org/projects/mocha
+
+== Examples
+
+* Quick Start - {Usage Examples}[link:examples/misc.html]
+* Traditional mocking - {Star Trek Example}[link:examples/mocha.html]
+* Setting expectations on real classes - {Order Example}[link:examples/stubba.html]
+* More examples on {Floehopper's Blog}[http://blog.floehopper.org]
+* {Mailing List Archives}[http://rubyforge.org/pipermail/mocha-developer/]
+
+== License
+
+Copyright Revieworld Ltd. 2006
+
+You may use, copy and redistribute this library under the same terms as {Ruby itself}[http://www.ruby-lang.org/en/LICENSE.txt] or under the {MIT license}[http://mocha.rubyforge.org/files/MIT-LICENSE.html].
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/RELEASE b/vendor/gems/mocha-0.5.6/RELEASE
new file mode 100644
index 0000000..0e8fb85
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/RELEASE
@@ -0,0 +1,188 @@
+= 0.5.5 (r167)
+
+- Renamed Matches parameter matcher to RegexpMatches for clarity.
+- Added noframes tag to rdoc index to assist Google.
+
+= 0.5.4 (r166)
+
+- Added matches parameter matcher for matching regular expressions.
+
+= 0.5.3 (r165)
+
+- Attempt to fix packaging problems by switching to newer version (1.15.1) of gnutar and setting COPY_EXTENDED_ATTRIBUTES_DISABLE environment variable.
+- Removed unused ExpectationSequenceError exception.
+- Added instance_of and kind_of parameter matchers.
+- Added Google Webmaster meta tag to rdoc template header.
+- Put Google Webmaster meta tag in the right header i.e. the one for the index page.
+
+= 0.5.2 (r159)
+
+- Fix bug 11885 - "never doesn't work with stub_everything" submitted by Alexander Lang. In fixing this bug, also fixed undiscoverd bug where expected & actual invocation counts were being incorrectly reported which seems to have been introduced when fixes were added for invocation dispatch (see MockedMethodDispatchAcceptanceTest).
+- Previously when an expectation did not allow more invocations, it was treated as not matching. Now we prefer matching expectations which allow more invocations, but still match expectations which cannot allow more invocations. I think this may be overcomplicating things, but let's see how it goes.
+
+= 0.5.1 (r149)
+
+- Fixed bug #11583 "Mocha 0.5.0 throwing unexpected warnings". Also switched on ruby warning for all rake test tasks. Fixed majority of warnings, but some left to fix.
+
+= 0.5.0 (r147)
+
+- Parameter Matchers - I’ve added a few Hamcrest-style parameter matchers which are designed to be used inside Expectation#with. The following matchers are currently available: anything(), includes(), has_key(), has_value(), has_entry(), all_of() & any_of(). More to follow soon. The idea is eventually to get rid of the nasty parameter_block option on Expectation#with.
+
+  object = mock()
+  object.expects(:method).with(has_key('key_1'))
+  object.method('key_1' => 1, 'key_2' => 2)
+  # no verification error raised
+
+  object = mock()
+  object.expects(:method).with(has_key('key_1'))
+  object.method('key_2' => 2)
+  # verification error raised, because method was not called with Hash containing key: 'key_1'
+
+- Values Returned and Exceptions Raised on Consecutive Invocations - Allow multiple calls to Expectation#returns and Expectation#raises to build up a sequence of responses to invocations on the mock. Added syntactic sugar method Expectation#then to allow more readable expectations.
+
+  object = mock()
+  object.stubs(:method).returns(1, 2).then.raises(Exception).then.returns(4)
+  object.method # => 1
+  object.method # => 2
+  object.method # => raises exception of class Exception
+  object.method # => 4
+
+- Yields on Consecutive Invocations - Allow multiple calls to yields on single expectation to allow yield parameters to be specified for consecutive invocations.
+
+  object = mock()
+  object.stubs(:method).yields(1, 2).then.yields(3)
+  object.method { |*values| p values } # => [1, 2]
+  object.method { |*values| p values } # => [3]
+
+- Multiple Yields on Single Invocation - Added Expectation#multiple_yields to allow a mocked or stubbed method to yield multiple times for a single invocation.
+
+  object = mock()
+  object.stubs(:method).multiple_yields([1, 2], [3])
+  object.method { |*values| p values } # => [1, 2] # => [3]
+
+- Invocation Dispatch - Expectations were already being matched in reverse order i.e. the most recently defined one was being found first. This is still the case, but we now stop matching an expectation when its maximum number of expected invocations is reached. c.f. JMock v1. A stub will never stop matching by default. Hopefully this means we can soon get rid of the need to pass a Proc to Expectation#returns.
+
+  object = mock()
+  object.stubs(:method).returns(2)
+  object.expects(:method).once.returns(1)
+  object.method # => 1
+  object.method # => 2
+  object.method # => 2
+  # no verification error raised
+
+  # The following should still work...
+
+  Time.stubs(:now).returns(Time.parse('Mon Jan 01 00:00:00 UTC 2007'))
+  Time.now # => Mon Jan 01 00:00:00 UTC 2007
+  Time.stubs(:now).returns(Time.parse('Thu Feb 01 00:00:00 UTC 2007'))
+  Time.now # => Thu Feb 01 00:00:00 UTC 2007
+  
+- Deprecate passing an instance of Proc to Expectation#returns.
+- Explicitly include all Rakefile dependencies in project.
+- Fixed old Stubba example.
+- Fix so that it is possible for a stubbed method to raise an Interrupt exception without a message in Ruby 1.8.6
+- Added responds_like and quacks_like.
+- Capture standard object methods before Mocha adds any.
+- Added Expectation#once method to make interface less surprising.
+- Use Rake::TestTask to run tests. Created three separate tasks to run unit, integration & acceptance tests. Split inspect_test into one file per TestCase. Deleted superfluous all_tests file.
+- Fiddled with mocha_inspect and tests to give more sensible results on x86 platform.
+- Fixed bug #7834 "infinite_range.rb makes incorrect assumption about to_f" logged by James Moore.
+
+= 0.4.0 (r92)
+
+- Allow naming of mocks (patch from Chris Roos).
+- Specify multiple return values for consecutive calls.
+- Improved consistency of expectation error messages.
+- Allow mocking of Object instance methods e.g. kind_of?, type.
+- Provide aliased versions of #expects and #stubs to allow mocking of these methods.
+- Added at_least, at_most, at_most_once methods to expectation.
+- Allow expects and stubs to take a hash of method and return values.
+- Eliminate warning: "instance variable @yield not initialized" (patch from Xavier Shay).
+- Restore instance methods on partial mocks (patch from Chris Roos).
+- Allow stubbing of a method with non-word characters in its name (patch from Paul Battley).
+- Removed coupling to Test::Unit.
+- Allow specified exception instance to be raised (patch from Chris Roos).
+- Make mock object_id appear in hex like normal Ruby inspect (patch from Paul Battley).
+- Fix path to object.rb in rdoc rake task (patch from Tomas Pospisek).
+- Reverse order in which expectations are matched, so that last expectation is matched first. This allows e.g. a call to #stubs to be effectively overridden by a call to #expects (patch from Tobias Lutke).
+- Stubba & SmartTestCase modules incorporated into Mocha module so only need to require 'mocha' - no longer need to require 'stubba'.
+- AutoMocha removed.
+
+= 0.3.3
+
+- Quick bug fix to restore instance methods on partial mocks (for Kevin Clark).
+
+= 0.3.2
+
+- Examples added.
+
+= 0.3.1
+
+- Dual licensing with MIT license added.
+
+= 0.3.0
+
+* Rails plugin.
+* Auto-verify for expectations on concrete classes.
+* Include each expectation verification in the test result assertion count.
+* Filter out noise from assertion backtraces.
+* Point assertion backtrace to line where failing expectation was created.
+* New yields method for expectations.
+* Create stubs which stub all method calls.
+* Mocks now respond_to? expected methods.
+
+= 0.2.1
+
+* Rename MochaAcceptanceTest::Rover#move method to avoid conflict with Rake (in Ruby 1.8.4 only?)
+
+= 0.2.0
+
+* Small change to SetupAndTeardown#teardown_stubs suggested by Luke Redpath (http://www.lukeredpath.co.uk) to allow use of Stubba with RSpec (http://rspec.rubyforge.org).
+* Reorganized directory structure and extracted addition of setup and teardown methods into SmartTestCase mini-library.
+* Addition of auto-verify for Mocha (but not Stubba). This means there is more significance in the choice of expects or stubs in that any expects on a mock will automatically get verified.
+
+So instead of...
+
+  wotsit = Mocha.new
+  wotsit.expects(:thingummy).with(5).returns(10)
+  doobrey = Doobrey.new(wotsit)
+  doobrey.hoojamaflip
+  wotsit.verify
+
+you need to do...
+
+  wotsit = mock()
+  wotsit.expects(:thingummy).with(5).returns(10)
+  doobrey = Doobrey.new(wotsit)
+  doobrey.hoojamaflip
+  # no need to verify
+
+There are also shortcuts as follows...
+
+instead of...
+
+  wotsit = Mocha.new
+  wotsit.expects(:thingummy).returns(10)
+  wotsit.expects(:summat).returns(25)
+
+you can have...
+
+  wotsit = mock(:thingummy => 5, :summat => 25)
+
+and instead of...
+
+  wotsit = Mocha.new
+  wotsit.stubs(:thingummy).returns(10)
+  wotsit.stubs(:summat).returns(25)
+
+you can have...
+
+  wotsit = stub(:thingummy => 5, :summat => 25)
+
+= 0.1.2
+
+* Minor tweaks
+
+= 0.1.1
+
+* Initial release.
diff --git a/vendor/gems/mocha-0.5.6/Rakefile b/vendor/gems/mocha-0.5.6/Rakefile
new file mode 100644
index 0000000..2e2f728
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/Rakefile
@@ -0,0 +1,149 @@
+require 'rubygems'
+require 'rake/rdoctask'
+require 'rake/gempackagetask'
+require 'rake/testtask'
+require 'rake/contrib/sshpublisher'
+
+module Mocha
+  VERSION = "0.5.6"
+end
+
+desc "Run all tests"
+task :default => :test_all
+
+task :test_all => [:test_unit, :test_integration, :test_acceptance]
+
+desc "Run unit tests"
+Rake::TestTask.new(:test_unit) do |t|
+  t.libs << 'test'
+  t.test_files = FileList['test/unit/**/*_test.rb']
+  t.verbose = true
+  t.warning = true
+end
+
+desc "Run integration tests"
+Rake::TestTask.new(:test_integration) do |t|
+  t.libs << 'test'
+  t.test_files = FileList['test/integration/*_test.rb']
+  t.verbose = true
+  t.warning = true
+end
+
+desc "Run acceptance tests"
+Rake::TestTask.new(:test_acceptance) do |t|
+  t.libs << 'test'
+  t.test_files = FileList['test/acceptance/*_test.rb']
+  t.verbose = true
+  t.warning = true
+end
+
+desc 'Generate RDoc'
+Rake::RDocTask.new do |task|
+  task.main = 'README'
+  task.title = "Mocha #{Mocha::VERSION}"
+  task.rdoc_dir = 'doc'
+  task.template = File.expand_path(File.join(File.dirname(__FILE__), "templates", "html_with_google_analytics"))
+  task.rdoc_files.include('README', 'RELEASE', 'COPYING', 'MIT-LICENSE', 'agiledox.txt', 'lib/mocha/auto_verify.rb', 'lib/mocha/mock.rb', 'lib/mocha/expectation.rb', 'lib/mocha/object.rb', 'lib/mocha/parameter_matchers.rb', 'lib/mocha/parameter_matchers')
+end
+task :rdoc => :examples
+
+desc "Upload RDoc to RubyForge"
+task :publish_rdoc => [:rdoc, :examples] do
+  Rake::SshDirPublisher.new("jamesmead at rubyforge.org", "/var/www/gforge-projects/mocha", "doc").upload
+end
+
+desc "Generate agiledox-like documentation for tests"
+file 'agiledox.txt' do
+  File.open('agiledox.txt', 'w') do |output|
+    tests = FileList['test/**/*_test.rb']
+    tests.each do |file|
+      m = %r".*/([^/].*)_test.rb".match(file)
+      output << m[1]+" should:\n"
+      test_definitions = File::readlines(file).select {|line| line =~ /.*def test.*/}
+      test_definitions.sort.each do |definition|
+        m = %r"test_(should_)?(.*)".match(definition)
+        output << " - "+m[2].gsub(/_/," ") << "\n"
+      end
+    end
+  end
+end
+
+desc "Convert example ruby files to syntax-highlighted html"
+task :examples do
+  $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "vendor", "coderay-0.7.4.215", "lib"))
+  require 'coderay'
+  mkdir_p 'doc/examples'
+  File.open('doc/examples/coderay.css', 'w') do |output|
+    output << CodeRay::Encoders[:html]::CSS.new.stylesheet
+  end
+  ['mocha', 'stubba', 'misc'].each do |filename|
+    File.open("doc/examples/#{filename}.html", 'w') do |file|
+      file << "<html>"
+      file << "<head>"
+      file << %q(<link rel="stylesheet" media="screen" href="coderay.css" type="text/css">)
+      file << "</head>"
+      file << "<body>"
+      file << CodeRay.scan_file("examples/#{filename}.rb").html.div
+      file << "</body>"
+      file << "</html>"
+    end
+  end
+end
+
+Gem::manage_gems
+
+specification = Gem::Specification.new do |s|
+  s.name   = "mocha"
+  s.summary = "Mocking and stubbing library"
+  s.version = Mocha::VERSION
+  s.platform = Gem::Platform::RUBY
+  s.author = 'James Mead'
+  s.description = <<-EOF
+    Mocking and stubbing library with JMock/SchMock syntax, which allows mocking and stubbing of methods on real (non-mock) classes.
+  EOF
+  s.email = 'mocha-developer at rubyforge.org'
+  s.homepage = 'http://mocha.rubyforge.org'
+  s.rubyforge_project = 'mocha'
+
+  s.has_rdoc = true
+  s.extra_rdoc_files = ['README', 'COPYING']
+  s.rdoc_options << '--title' << 'Mocha' << '--main' << 'README' << '--line-numbers'
+                         
+  s.autorequire = 'mocha'
+  s.add_dependency('rake')
+  s.files = FileList['{lib,test,examples}/**/*.rb', '[A-Z]*'].exclude('TODO').to_a
+end
+
+Rake::GemPackageTask.new(specification) do |package|
+   package.need_zip = true
+   package.need_tar = true
+end
+
+task :verify_user do
+  raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
+end
+
+task :verify_password do
+  raise "RUBYFORGE_PASSWORD environment variable not set!" unless ENV['RUBYFORGE_PASSWORD']
+end
+
+desc "Publish package files on RubyForge."
+task :publish_packages => [:verify_user, :verify_password, :package] do
+  $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "vendor", "meta_project-0.4.15", "lib"))
+  require 'meta_project'
+  require 'rake/contrib/xforge'
+  release_files = FileList[
+    "pkg/mocha-#{Mocha::VERSION}.gem",
+    "pkg/mocha-#{Mocha::VERSION}.tgz",
+    "pkg/mocha-#{Mocha::VERSION}.zip"
+  ]
+
+  Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new('mocha')) do |release|
+    release.user_name = ENV['RUBYFORGE_USER']
+    release.password = ENV['RUBYFORGE_PASSWORD']
+    release.files = release_files.to_a
+    release.release_name = "Mocha #{Mocha::VERSION}"
+    release.release_changes = ''
+    release.release_notes = ''
+  end
+end
diff --git a/vendor/gems/mocha-0.5.6/examples/._misc.rb b/vendor/gems/mocha-0.5.6/examples/._misc.rb
new file mode 100644
index 0000000..c425bb3
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/examples/._misc.rb differ
diff --git a/vendor/gems/mocha-0.5.6/examples/._mocha.rb b/vendor/gems/mocha-0.5.6/examples/._mocha.rb
new file mode 100644
index 0000000..0c1998d
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/examples/._mocha.rb differ
diff --git a/vendor/gems/mocha-0.5.6/examples/._stubba.rb b/vendor/gems/mocha-0.5.6/examples/._stubba.rb
new file mode 100644
index 0000000..4eae8fa
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/examples/._stubba.rb differ
diff --git a/vendor/gems/mocha-0.5.6/examples/misc.rb b/vendor/gems/mocha-0.5.6/examples/misc.rb
new file mode 100644
index 0000000..1cb8b55
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/examples/misc.rb
@@ -0,0 +1,44 @@
+require 'test/unit'
+require 'rubygems'
+require 'mocha'
+
+class MiscExampleTest < Test::Unit::TestCase
+  
+  def test_mocking_a_class_method
+    product = Product.new
+    Product.expects(:find).with(1).returns(product)
+    assert_equal product, Product.find(1)
+  end
+
+  def test_mocking_an_instance_method_on_a_real_object
+    product = Product.new
+    product.expects(:save).returns(true)
+    assert product.save
+  end
+
+  def test_stubbing_instance_methods_on_real_objects
+    prices = [stub(:pence => 1000), stub(:pence => 2000)]
+    product = Product.new
+    product.stubs(:prices).returns(prices)
+    assert_equal [1000, 2000], product.prices.collect {|p| p.pence}
+  end
+
+  def test_stubbing_an_instance_method_on_all_instances_of_a_class
+    Product.any_instance.stubs(:name).returns('stubbed_name')
+    product = Product.new
+    assert_equal 'stubbed_name', product.name
+  end
+
+  def test_traditional_mocking
+    object = mock()
+    object.expects(:expected_method).with(:p1, :p2).returns(:result)
+    assert_equal :result, object.expected_method(:p1, :p2)
+  end
+
+  def test_shortcuts
+    object = stub(:method1 => :result1, :method2 => :result2)
+    assert_equal :result1, object.method1
+    assert_equal :result2, object.method2
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/examples/mocha.rb b/vendor/gems/mocha-0.5.6/examples/mocha.rb
new file mode 100644
index 0000000..863270d
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/examples/mocha.rb
@@ -0,0 +1,26 @@
+class Enterprise
+
+  def initialize(dilithium)
+    @dilithium = dilithium
+  end
+
+  def go(warp_factor)
+    warp_factor.times { @dilithium.nuke(:anti_matter) }
+  end
+
+end
+
+require 'test/unit'
+require 'rubygems'
+require 'mocha'
+
+class EnterpriseTest < Test::Unit::TestCase
+
+  def test_should_boldly_go
+    dilithium = mock()
+    dilithium.expects(:nuke).with(:anti_matter).at_least_once  # auto-verified at end of test
+    enterprise = Enterprise.new(dilithium)
+    enterprise.go(2)
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/examples/stubba.rb b/vendor/gems/mocha-0.5.6/examples/stubba.rb
new file mode 100644
index 0000000..2788d1b
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/examples/stubba.rb
@@ -0,0 +1,65 @@
+class Order
+
+  attr_accessor :shipped_on
+
+  def total_cost
+    line_items.inject(0) { |total, line_item| total + line_item.price } + shipping_cost
+  end
+
+  def total_weight
+    line_items.inject(0) { |total, line_item| total + line_item.weight }
+  end
+
+  def shipping_cost
+    total_weight * 5 + 10
+  end
+
+  class << self
+
+    def find_all
+      # Database.connection.execute('select * from orders...
+    end
+  
+    def number_shipped_since(date)
+      find_all.select { |order| order.shipped_on > date }.length
+    end
+
+    def unshipped_value
+      find_all.inject(0) { |total, order| order.shipped_on ? total : total + order.total_cost }
+    end
+
+  end
+
+end
+
+require 'test/unit'
+require 'rubygems'
+require 'mocha'
+
+class OrderTest < Test::Unit::TestCase
+
+  # illustrates stubbing instance method
+  def test_should_calculate_shipping_cost_based_on_total_weight
+    order = Order.new
+    order.stubs(:total_weight).returns(10)
+    assert_equal 60, order.shipping_cost
+  end
+
+  # illustrates stubbing class method
+  def test_should_count_number_of_orders_shipped_after_specified_date
+    now = Time.now; week_in_secs = 7 * 24 * 60 * 60
+    order_1 = Order.new; order_1.shipped_on = now - 1 * week_in_secs
+    order_2 = Order.new; order_2.shipped_on = now - 3 * week_in_secs
+    Order.stubs(:find_all).returns([order_1, order_2])
+    assert_equal 1, Order.number_shipped_since(now - 2 * week_in_secs)
+  end
+
+  # illustrates stubbing instance method for all instances of a class
+  def test_should_calculate_value_of_unshipped_orders
+    Order.stubs(:find_all).returns([Order.new, Order.new, Order.new])
+    Order.any_instance.stubs(:shipped_on).returns(nil)
+    Order.any_instance.stubs(:total_cost).returns(10)
+    assert_equal 30, Order.unshipped_value
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/._mocha.rb b/vendor/gems/mocha-0.5.6/lib/._mocha.rb
new file mode 100644
index 0000000..cf6ff48
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/._mocha.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha.rb b/vendor/gems/mocha-0.5.6/lib/mocha.rb
new file mode 100644
index 0000000..5857115
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha.rb
@@ -0,0 +1,19 @@
+require 'mocha_standalone'
+require 'mocha/test_case_adapter'
+
+require 'test/unit/testcase'
+
+module Test
+
+  module Unit
+
+    class TestCase
+  
+      include Mocha::Standalone
+      include Mocha::TestCaseAdapter
+      
+    end
+
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._any_instance_method.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._any_instance_method.rb
new file mode 100644
index 0000000..00711bd
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._any_instance_method.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._auto_verify.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._auto_verify.rb
new file mode 100644
index 0000000..b0167df
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._auto_verify.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._central.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._central.rb
new file mode 100644
index 0000000..8515018
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._central.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._class_method.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._class_method.rb
new file mode 100644
index 0000000..66871a5
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._class_method.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._deprecation.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._deprecation.rb
new file mode 100644
index 0000000..3e11a4d
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._deprecation.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._expectation.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._expectation.rb
new file mode 100644
index 0000000..2deed46
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._expectation.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._expectation_error.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._expectation_error.rb
new file mode 100644
index 0000000..dbb6154
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._expectation_error.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._expectation_list.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._expectation_list.rb
new file mode 100644
index 0000000..21a5f32
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._expectation_list.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._infinite_range.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._infinite_range.rb
new file mode 100644
index 0000000..07e0b70
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._infinite_range.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._inspect.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._inspect.rb
new file mode 100644
index 0000000..28d27ab
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._inspect.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._instance_method.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._instance_method.rb
new file mode 100644
index 0000000..c11d0ea
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._instance_method.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._metaclass.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._metaclass.rb
new file mode 100644
index 0000000..3ab4a8b
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._metaclass.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._method_matcher.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._method_matcher.rb
new file mode 100644
index 0000000..392843f
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._method_matcher.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._missing_expectation.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._missing_expectation.rb
new file mode 100644
index 0000000..4049e36
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._missing_expectation.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._mock.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._mock.rb
new file mode 100644
index 0000000..8eefd13
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._mock.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._object.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._object.rb
new file mode 100644
index 0000000..2fa785b
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._object.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._parameter_matchers.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._parameter_matchers.rb
new file mode 100644
index 0000000..1a81dea
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._parameter_matchers.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._parameters_matcher.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._parameters_matcher.rb
new file mode 100644
index 0000000..de250a8
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._parameters_matcher.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._pretty_parameters.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._pretty_parameters.rb
new file mode 100644
index 0000000..0a4f485
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._pretty_parameters.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._return_values.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._return_values.rb
new file mode 100644
index 0000000..0d41af3
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._return_values.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._sequence.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._sequence.rb
new file mode 100644
index 0000000..af24948
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._sequence.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._setup_and_teardown.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._setup_and_teardown.rb
new file mode 100644
index 0000000..fb1bde1
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._setup_and_teardown.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._single_return_value.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._single_return_value.rb
new file mode 100644
index 0000000..fec4c56
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._single_return_value.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._standalone.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._standalone.rb
new file mode 100644
index 0000000..f33f028
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._standalone.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._test_case_adapter.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._test_case_adapter.rb
new file mode 100644
index 0000000..99a49dc
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._test_case_adapter.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/._yield_parameters.rb b/vendor/gems/mocha-0.5.6/lib/mocha/._yield_parameters.rb
new file mode 100644
index 0000000..a9646d7
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/._yield_parameters.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/any_instance_method.rb b/vendor/gems/mocha-0.5.6/lib/mocha/any_instance_method.rb
new file mode 100644
index 0000000..4d55293
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/any_instance_method.rb
@@ -0,0 +1,35 @@
+require 'mocha/class_method'
+
+module Mocha
+
+  class AnyInstanceMethod < ClassMethod
+  
+    def unstub
+      remove_new_method
+      restore_original_method
+      stubbee.any_instance.reset_mocha
+    end
+    
+    def mock
+      stubbee.any_instance.mocha
+    end
+   
+    def hide_original_method
+      stubbee.class_eval "alias_method :#{hidden_method}, :#{method}" if stubbee.method_defined?(method)
+    end
+
+    def define_new_method
+      stubbee.class_eval "def #{method}(*args, &block); self.class.any_instance.mocha.method_missing(:#{method}, *args, &block); end"
+    end
+
+    def remove_new_method
+      stubbee.class_eval "remove_method :#{method}"
+    end
+
+    def restore_original_method
+      stubbee.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.method_defined?(hidden_method)
+    end
+
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/auto_verify.rb b/vendor/gems/mocha-0.5.6/lib/mocha/auto_verify.rb
new file mode 100644
index 0000000..896648b
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/auto_verify.rb
@@ -0,0 +1,118 @@
+require 'mocha/mock'
+require 'mocha/sequence'
+
+module Mocha # :nodoc:
+  
+  # Methods added to TestCase allowing creation of traditional mock objects.
+  #
+  # Mocks created this way will have their expectations automatically verified at the end of the test.
+  #
+  # See Mock for methods on mock objects.
+  module AutoVerify
+  
+    def mocks # :nodoc:
+      @mocks ||= []
+    end
+  
+    def reset_mocks # :nodoc:
+      @mocks = nil
+    end
+    
+    # :call-seq: mock(name, &block) -> mock object
+    #            mock(expected_methods = {}, &block) -> mock object
+    #            mock(name, expected_methods = {}, &block) -> mock object
+    #
+    # Creates a mock object.
+    #
+    # +name+ is a +String+ identifier for the mock object.
+    #
+    # +expected_methods+ is a +Hash+ with expected method name symbols as keys and corresponding return values as values.
+    #
+    # +block+ is a block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs.
+    #
+    # Note that (contrary to expectations set up by #stub) these expectations <b>must</b> be fulfilled during the test.
+    #   def test_product
+    #     product = mock('ipod_product', :manufacturer => 'ipod', :price => 100)
+    #     assert_equal 'ipod', product.manufacturer
+    #     assert_equal 100, product.price
+    #     # an error will be raised unless both Product#manufacturer and Product#price have been called
+    #   end 
+    def mock(*arguments, &block)
+      name = arguments.shift if arguments.first.is_a?(String)
+      expectations = arguments.shift || {}
+      mock = Mock.new(name, &block)
+      mock.expects(expectations)
+      mocks << mock
+      mock
+    end
+  
+    # :call-seq: stub(name, &block) -> mock object
+    #            stub(stubbed_methods = {}, &block) -> mock object
+    #            stub(name, stubbed_methods = {}, &block) -> mock object
+    #
+    # Creates a mock object.
+    #
+    # +name+ is a +String+ identifier for the mock object.
+    #
+    # +stubbed_methods+ is a +Hash+ with stubbed method name symbols as keys and corresponding return values as values.
+    #
+    # +block+ is a block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs.
+    #
+    # Note that (contrary to expectations set up by #mock) these expectations <b>need not</b> be fulfilled during the test.
+    #   def test_product
+    #     product = stub('ipod_product', :manufacturer => 'ipod', :price => 100)
+    #     assert_equal 'ipod', product.manufacturer
+    #     assert_equal 100, product.price
+    #     # an error will not be raised even if Product#manufacturer and Product#price have not been called
+    #   end
+    def stub(*arguments, &block)
+      name = arguments.shift if arguments.first.is_a?(String)
+      expectations = arguments.shift || {}
+      stub = Mock.new(name, &block)
+      stub.stubs(expectations)
+      mocks << stub
+      stub
+    end
+  
+    # :call-seq: stub_everything(name, &block) -> mock object
+    #            stub_everything(stubbed_methods = {}, &block) -> mock object
+    #            stub_everything(name, stubbed_methods = {}, &block) -> mock object
+    #
+    # Creates a mock object that accepts calls to any method.
+    #
+    # By default it will return +nil+ for any method call.
+    #
+    # +block+ is a block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs.
+    #
+    # +name+ and +stubbed_methods+ work in the same way as for #stub.
+    #   def test_product
+    #     product = stub_everything('ipod_product', :price => 100)
+    #     assert_nil product.manufacturer
+    #     assert_nil product.any_old_method
+    #     assert_equal 100, product.price
+    #   end
+    def stub_everything(*arguments, &block)
+      name = arguments.shift if arguments.first.is_a?(String)
+      expectations = arguments.shift || {}
+      stub = Mock.new(name, &block)
+      stub.stub_everything
+      stub.stubs(expectations)
+      mocks << stub
+      stub
+    end
+    
+    def verify_mocks # :nodoc:
+      mocks.each { |mock| mock.verify { yield if block_given? } }
+    end
+
+    def teardown_mocks # :nodoc:
+      reset_mocks
+    end
+    
+    def sequence(name) # :nodoc:
+      Sequence.new(name)
+    end
+  
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/central.rb b/vendor/gems/mocha-0.5.6/lib/mocha/central.rb
new file mode 100644
index 0000000..0445f21
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/central.rb
@@ -0,0 +1,35 @@
+module Mocha
+  
+  class Central
+  
+    attr_accessor :stubba_methods
+  
+    def initialize
+      self.stubba_methods = []
+    end
+   
+    def stub(method)
+      unless stubba_methods.include?(method)
+        method.stub 
+        stubba_methods.push method
+      end
+    end
+    
+    def verify_all(&block)
+      unique_mocks.each { |mock| mock.verify(&block) }
+    end
+    
+    def unique_mocks
+      stubba_methods.inject({}) { |mocks, method| mocks[method.mock.__id__] = method.mock; mocks }.values
+    end
+  
+    def unstub_all
+      while stubba_methods.length > 0
+        method = stubba_methods.pop
+        method.unstub
+      end
+    end
+
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/class_method.rb b/vendor/gems/mocha-0.5.6/lib/mocha/class_method.rb
new file mode 100644
index 0000000..e2178be
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/class_method.rb
@@ -0,0 +1,66 @@
+require 'mocha/metaclass'
+
+module Mocha
+
+  class ClassMethod
+  
+    attr_reader :stubbee, :method
+   
+    def initialize(stubbee, method)
+      @stubbee, @method = stubbee, method
+    end
+  
+    def stub
+      hide_original_method
+      define_new_method
+    end
+  
+    def unstub
+      remove_new_method
+      restore_original_method
+      stubbee.reset_mocha
+    end
+    
+    def mock
+      stubbee.mocha
+    end
+  
+    def hide_original_method
+      stubbee.__metaclass__.class_eval "alias_method :#{hidden_method}, :#{method}" if stubbee.__metaclass__.method_defined?(method)
+    end
+  
+    def define_new_method
+      stubbee.__metaclass__.class_eval "def #{method}(*args, &block); mocha.method_missing(:#{method}, *args, &block); end"
+    end
+  
+    def remove_new_method
+      stubbee.__metaclass__.class_eval "remove_method :#{method}"
+    end
+  
+    def restore_original_method
+      stubbee.__metaclass__.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.__metaclass__.method_defined?(hidden_method)
+    end
+  
+    def hidden_method
+      if RUBY_VERSION < '1.9'
+        method_name = method.to_s.gsub(/\W/) { |s| "_substituted_character_#{s[0]}_" }
+      else
+        method_name = method.to_s.gsub(/\W/) { |s| "_substituted_character_#{s.ord}_" }
+      end
+      "__stubba__#{method_name}__stubba__"
+    end  
+  
+    def eql?(other)
+      return false unless (other.class == self.class)
+      (stubbee == other.stubbee) and (method == other.method)
+    end
+  
+    alias_method :==, :eql?
+  
+    def to_s
+      "#{stubbee}.#{method}"
+    end
+
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/deprecation.rb b/vendor/gems/mocha-0.5.6/lib/mocha/deprecation.rb
new file mode 100644
index 0000000..7448510
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/deprecation.rb
@@ -0,0 +1,22 @@
+module Mocha
+  
+  class Deprecation
+    
+    class << self
+      
+      attr_accessor :mode, :messages
+      
+      def warning(message)
+        @messages << message
+        $stderr.puts "Mocha deprecation warning: #{message}" unless mode == :disabled
+        $stderr.puts caller.join("\n  ") if mode == :debug
+      end
+
+    end
+  
+    self.mode = :enabled
+    self.messages = []
+    
+  end
+   
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/exception_raiser.rb b/vendor/gems/mocha-0.5.6/lib/mocha/exception_raiser.rb
new file mode 100644
index 0000000..266e209
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/exception_raiser.rb
@@ -0,0 +1,17 @@
+module Mocha # :nodoc:
+  
+  class ExceptionRaiser # :nodoc:
+    
+    def initialize(exception, message)
+      @exception, @message = exception, message
+    end
+    
+    def evaluate
+      raise @exception, @exception.to_s if @exception == Interrupt
+      raise @exception, @message if @message
+      raise @exception
+    end
+    
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/expectation.rb b/vendor/gems/mocha-0.5.6/lib/mocha/expectation.rb
new file mode 100644
index 0000000..e3da253
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/expectation.rb
@@ -0,0 +1,384 @@
+require 'mocha/infinite_range'
+require 'mocha/method_matcher'
+require 'mocha/parameters_matcher'
+require 'mocha/expectation_error'
+require 'mocha/return_values'
+require 'mocha/exception_raiser'
+require 'mocha/yield_parameters'
+require 'mocha/is_a'
+
+module Mocha # :nodoc:
+  
+  # Methods on expectations returned from Mock#expects, Mock#stubs, Object#expects and Object#stubs.
+  class Expectation
+  
+    # :call-seq: times(range) -> expectation
+    #
+    # Modifies expectation so that the number of calls to the expected method must be within a specific +range+.
+    #
+    # +range+ can be specified as an exact integer or as a range of integers
+    #   object = mock()
+    #   object.expects(:expected_method).times(3)
+    #   3.times { object.expected_method }
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).times(3)
+    #   2.times { object.expected_method }
+    #   # => verify fails
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).times(2..4)
+    #   3.times { object.expected_method }
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).times(2..4)
+    #   object.expected_method
+    #   # => verify fails
+    def times(range)
+      @expected_count = range
+      self
+    end
+  
+    # :call-seq: once() -> expectation
+    #
+    # Modifies expectation so that the expected method must be called exactly once.
+    # Note that this is the default behaviour for an expectation, but you may wish to use it for clarity/emphasis.
+    #   object = mock()
+    #   object.expects(:expected_method).once
+    #   object.expected_method
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).once
+    #   object.expected_method
+    #   object.expected_method
+    #   # => verify fails
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).once
+    #   # => verify fails
+    def once()
+      times(1)
+      self
+    end
+  
+    # :call-seq: never() -> expectation
+    #
+    # Modifies expectation so that the expected method must never be called.
+    #   object = mock()
+    #   object.expects(:expected_method).never
+    #   object.expected_method
+    #   # => verify fails
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).never
+    #   object.expected_method
+    #   # => verify succeeds
+    def never
+      times(0)
+      self
+    end
+  
+    # :call-seq: at_least(minimum_number_of_times) -> expectation
+    #
+    # Modifies expectation so that the expected method must be called at least a +minimum_number_of_times+.
+    #   object = mock()
+    #   object.expects(:expected_method).at_least(2)
+    #   3.times { object.expected_method }
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).at_least(2)
+    #   object.expected_method
+    #   # => verify fails
+    def at_least(minimum_number_of_times)
+      times(Range.at_least(minimum_number_of_times))
+      self
+    end
+  
+    # :call-seq: at_least_once() -> expectation
+    #
+    # Modifies expectation so that the expected method must be called at least once.
+    #   object = mock()
+    #   object.expects(:expected_method).at_least_once
+    #   object.expected_method
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).at_least_once
+    #   # => verify fails
+    def at_least_once()
+      at_least(1)
+      self
+    end
+  
+    # :call-seq: at_most(maximum_number_of_times) -> expectation
+    #
+    # Modifies expectation so that the expected method must be called at most a +maximum_number_of_times+.
+    #   object = mock()
+    #   object.expects(:expected_method).at_most(2)
+    #   2.times { object.expected_method }
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).at_most(2)
+    #   3.times { object.expected_method }
+    #   # => verify fails
+    def at_most(maximum_number_of_times)
+      times(Range.at_most(maximum_number_of_times))
+      self
+    end
+  
+    # :call-seq: at_most_once() -> expectation
+    #
+    # Modifies expectation so that the expected method must be called at most once.
+    #   object = mock()
+    #   object.expects(:expected_method).at_most_once
+    #   object.expected_method
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).at_most_once
+    #   2.times { object.expected_method }
+    #   # => verify fails
+    def at_most_once()
+      at_most(1)
+      self
+    end
+  
+    # :call-seq: with(*expected_parameters, &matching_block) -> expectation
+    #
+    # Modifies expectation so that the expected method must be called with +expected_parameters+.
+    #   object = mock()
+    #   object.expects(:expected_method).with(:param1, :param2)
+    #   object.expected_method(:param1, :param2)
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).with(:param1, :param2)
+    #   object.expected_method(:param3)
+    #   # => verify fails
+    # May be used with parameter matchers in Mocha::ParameterMatchers.
+    #
+    # If a +matching_block+ is given, the block is called with the parameters passed to the expected method.
+    # The expectation is matched if the block evaluates to +true+.
+    #   object = mock()
+    #   object.expects(:expected_method).with() { |value| value % 4 == 0 }
+    #   object.expected_method(16)
+    #   # => verify succeeds
+    #
+    #   object = mock()
+    #   object.expects(:expected_method).with() { |value| value % 4 == 0 }
+    #   object.expected_method(17)
+    #   # => verify fails
+    def with(*expected_parameters, &matching_block)
+      @parameters_matcher = ParametersMatcher.new(expected_parameters, &matching_block)
+      self
+    end
+  
+    # :call-seq: yields(*parameters) -> expectation
+    #
+    # Modifies expectation so that when the expected method is called, it yields with the specified +parameters+.
+    #   object = mock()
+    #   object.expects(:expected_method).yields('result')
+    #   yielded_value = nil
+    #   object.expected_method { |value| yielded_value = value }
+    #   yielded_value # => 'result'
+    # May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then.
+    #   object = mock()
+    #   object.stubs(:expected_method).yields(1).then.yields(2)
+    #   yielded_values_from_first_invocation = []
+    #   yielded_values_from_second_invocation = []
+    #   object.expected_method { |value| yielded_values_from_first_invocation << value } # first invocation
+    #   object.expected_method { |value| yielded_values_from_second_invocation << value } # second invocation
+    #   yielded_values_from_first_invocation # => [1]
+    #   yielded_values_from_second_invocation # => [2]
+    def yields(*parameters)
+      @yield_parameters.add(*parameters)
+      self
+    end
+    
+    # :call-seq: multiple_yields(*parameter_groups) -> expectation
+    #
+    # Modifies expectation so that when the expected method is called, it yields multiple times per invocation with the specified +parameter_groups+.
+    #   object = mock()
+    #   object.expects(:expected_method).multiple_yields(['result_1', 'result_2'], ['result_3'])
+    #   yielded_values = []
+    #   object.expected_method { |*values| yielded_values << values }
+    #   yielded_values # => [['result_1', 'result_2'], ['result_3]]
+    # May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then.
+    #   object = mock()
+    #   object.stubs(:expected_method).multiple_yields([1, 2], [3]).then.multiple_yields([4], [5, 6])
+    #   yielded_values_from_first_invocation = []
+    #   yielded_values_from_second_invocation = []
+    #   object.expected_method { |*values| yielded_values_from_first_invocation << values } # first invocation
+    #   object.expected_method { |*values| yielded_values_from_second_invocation << values } # second invocation
+    #   yielded_values_from_first_invocation # => [[1, 2], [3]]
+    #   yielded_values_from_second_invocation # => [[4], [5, 6]]
+    def multiple_yields(*parameter_groups)
+      @yield_parameters.multiple_add(*parameter_groups)
+      self
+    end
+    
+    # :call-seq: returns(value) -> expectation
+    #            returns(*values) -> expectation
+    #
+    # Modifies expectation so that when the expected method is called, it returns the specified +value+.
+    #   object = mock()
+    #   object.stubs(:stubbed_method).returns('result')
+    #   object.stubbed_method # => 'result'
+    #   object.stubbed_method # => 'result'
+    # If multiple +values+ are given, these are returned in turn on consecutive calls to the method.
+    #   object = mock()
+    #   object.stubs(:stubbed_method).returns(1, 2)
+    #   object.stubbed_method # => 1
+    #   object.stubbed_method # => 2
+    # May be called multiple times on the same expectation. Also see Expectation#then.
+    #   object = mock()
+    #   object.stubs(:expected_method).returns(1, 2).then.returns(3)
+    #   object.expected_method # => 1
+    #   object.expected_method # => 2
+    #   object.expected_method # => 3
+    # May be called in conjunction with Expectation#raises on the same expectation.
+    #   object = mock()
+    #   object.stubs(:expected_method).returns(1, 2).then.raises(Exception)
+    #   object.expected_method # => 1
+    #   object.expected_method # => 2
+    #   object.expected_method # => raises exception of class Exception1
+    # If +value+ is a +Proc+, then the expected method will return the result of calling <tt>Proc#call</tt>.
+    #
+    # This usage is _deprecated_.
+    # Use explicit multiple return values and/or multiple expectations instead.
+    #
+    # A +Proc+ instance will be treated the same as any other value in a future release.
+    #   object = mock()
+    #   object.stubs(:stubbed_method).returns(lambda { rand(100) })
+    #   object.stubbed_method # => 41
+    #   object.stubbed_method # => 77
+    def returns(*values)
+      @return_values += ReturnValues.build(*values)
+      self
+    end
+  
+    # :call-seq: raises(exception = RuntimeError, message = nil) -> expectation
+    #
+    # Modifies expectation so that when the expected method is called, it raises the specified +exception+ with the specified +message+.
+    #   object = mock()
+    #   object.expects(:expected_method).raises(Exception, 'message')
+    #   object.expected_method # => raises exception of class Exception and with message 'message'
+    # May be called multiple times on the same expectation. Also see Expectation#then.
+    #   object = mock()
+    #   object.stubs(:expected_method).raises(Exception1).then.raises(Exception2)
+    #   object.expected_method # => raises exception of class Exception1
+    #   object.expected_method # => raises exception of class Exception2
+    # May be called in conjunction with Expectation#returns on the same expectation.
+    #   object = mock()
+    #   object.stubs(:expected_method).raises(Exception).then.returns(2, 3)
+    #   object.expected_method # => raises exception of class Exception1
+    #   object.expected_method # => 2
+    #   object.expected_method # => 3
+    def raises(exception = RuntimeError, message = nil)
+      @return_values += ReturnValues.new(ExceptionRaiser.new(exception, message))
+      self
+    end
+
+    # :call-seq: then() -> expectation
+    #
+    # Syntactic sugar to improve readability. Has no effect on state of the expectation.
+    #   object = mock()
+    #   object.stubs(:expected_method).returns(1, 2).then.raises(Exception).then.returns(4)
+    #   object.expected_method # => 1
+    #   object.expected_method # => 2
+    #   object.expected_method # => raises exception of class Exception
+    #   object.expected_method # => 4
+    def then
+      self
+    end
+    
+    # :stopdoc:
+    
+    def in_sequence(*sequences)
+      sequences.each { |sequence| sequence.constrain_as_next_in_sequence(self) }
+      self
+    end
+    
+    attr_reader :backtrace
+
+    def initialize(mock, expected_method_name, backtrace = nil)
+      @mock = mock
+      @method_matcher = MethodMatcher.new(expected_method_name)
+      @parameters_matcher = ParametersMatcher.new
+      @ordering_constraints = []
+      @expected_count, @invoked_count = 1, 0
+      @return_values = ReturnValues.new
+      @yield_parameters = YieldParameters.new
+      @backtrace = backtrace || caller
+    end
+    
+    def add_ordering_constraint(ordering_constraint)
+      @ordering_constraints << ordering_constraint
+    end
+    
+    def in_correct_order?
+      @ordering_constraints.all? { |ordering_constraint| ordering_constraint.allows_invocation_now? }
+    end
+    
+    def matches_method?(method_name)
+      @method_matcher.match?(method_name)
+    end
+    
+    def match?(actual_method_name, *actual_parameters)
+      @method_matcher.match?(actual_method_name) && @parameters_matcher.match?(actual_parameters) && in_correct_order?
+    end
+    
+    def invocations_allowed?
+      if @expected_count.is_a?(Range) then
+        @invoked_count < @expected_count.last
+      else
+        @invoked_count < @expected_count
+      end
+    end
+
+    def satisfied?
+      if @expected_count.is_a?(Range) then
+        @invoked_count >= @expected_count.first
+      else
+        @invoked_count >= @expected_count
+      end
+    end
+  
+    def invoke
+      @invoked_count += 1
+      if block_given? then
+        @yield_parameters.next_invocation.each do |yield_parameters|
+          yield(*yield_parameters)
+        end
+      end
+      @return_values.next
+    end
+
+    def verify
+      yield(self) if block_given?
+      unless (@expected_count === @invoked_count) then
+        error = ExpectationError.new(error_message(@expected_count, @invoked_count), backtrace)
+        raise error
+      end
+    end
+    
+    def method_signature
+      signature = "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}"
+      signature << "; #{@ordering_constraints.map { |oc| oc.mocha_inspect }.join("; ")}" unless @ordering_constraints.empty?
+      signature
+    end
+    
+    def error_message(expected_count, actual_count)
+      "#{method_signature} - expected calls: #{expected_count.mocha_inspect}, actual calls: #{actual_count}"
+    end
+  
+    # :startdoc:
+    
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/expectation_error.rb b/vendor/gems/mocha-0.5.6/lib/mocha/expectation_error.rb
new file mode 100644
index 0000000..705571b
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/expectation_error.rb
@@ -0,0 +1,15 @@
+module Mocha
+
+  class ExpectationError < StandardError
+    
+    LIB_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), "..")) + File::SEPARATOR
+    
+    def initialize(message = nil, backtrace = [], lib_directory = LIB_DIRECTORY)
+      super(message)
+      filtered_backtrace = backtrace.reject { |location| Regexp.new(lib_directory).match(File.expand_path(location)) }
+      set_backtrace(filtered_backtrace)
+    end
+
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/expectation_list.rb b/vendor/gems/mocha-0.5.6/lib/mocha/expectation_list.rb
new file mode 100644
index 0000000..5ca13d5
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/expectation_list.rb
@@ -0,0 +1,46 @@
+module Mocha # :nodoc:
+
+  class ExpectationList
+
+    def initialize
+      @expectations = []
+    end
+
+    def add(expectation)
+      @expectations << expectation
+      expectation
+    end
+
+    def matches_method?(method_name)
+      @expectations.any? { |expectation| expectation.matches_method?(method_name) }
+    end
+
+    def similar(method_name)
+      @expectations.select { |expectation| expectation.matches_method?(method_name) }
+    end
+
+    def detect(method_name, *arguments)
+      expectations = @expectations.reverse.select { |e| e.match?(method_name, *arguments) }
+      expectation = expectations.detect { |e| e.invocations_allowed? }
+      expectation || expectations.first
+    end
+
+    def verify(&block)
+      @expectations.each { |expectation| expectation.verify(&block) }
+    end
+
+    def to_a
+      @expectations
+    end
+
+    def to_set
+      @expectations.to_set
+    end
+
+    def length
+      @expectations.length
+    end
+
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/infinite_range.rb b/vendor/gems/mocha-0.5.6/lib/mocha/infinite_range.rb
new file mode 100644
index 0000000..05dfe55
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/infinite_range.rb
@@ -0,0 +1,25 @@
+class Range
+  
+  def self.at_least(minimum_value)
+    Range.new(minimum_value, infinite)
+  end
+  
+  def self.at_most(maximum_value)
+    Range.new(-infinite, maximum_value, false)
+  end
+  
+  def self.infinite
+    1/0.0
+  end
+  
+  def mocha_inspect
+    if first.respond_to?(:to_f) and first.to_f.infinite? then
+      return "at most #{last}"
+    elsif last.respond_to?(:to_f) and last.to_f.infinite? then
+      return "at least #{first}"
+    else
+      to_s
+    end
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/inspect.rb b/vendor/gems/mocha-0.5.6/lib/mocha/inspect.rb
new file mode 100644
index 0000000..ad82ef7
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/inspect.rb
@@ -0,0 +1,39 @@
+require 'date'
+
+class Object
+  def mocha_inspect
+    address = self.__id__ * 2
+    address += 0x100000000 if address < 0
+    inspect =~ /#</ ? "#<#{self.class}:0x#{'%x' % address}>" : inspect
+  end
+end
+
+class String
+  def mocha_inspect
+    inspect.gsub(/\"/, "'")
+  end
+end
+
+class Array
+  def mocha_inspect
+    "[#{collect { |member| member.mocha_inspect }.join(', ')}]"
+  end
+end
+
+class Hash
+  def mocha_inspect
+    "{#{collect { |key, value| "#{key.mocha_inspect} => #{value.mocha_inspect}" }.join(', ')}}"
+  end
+end
+
+class Time
+  def mocha_inspect
+    "#{inspect} (#{to_f} secs)"
+  end
+end
+
+class Date
+  def mocha_inspect
+    to_s
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/instance_method.rb b/vendor/gems/mocha-0.5.6/lib/mocha/instance_method.rb
new file mode 100644
index 0000000..f0d4b04
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/instance_method.rb
@@ -0,0 +1,8 @@
+require 'mocha/class_method'
+
+module Mocha
+
+  class InstanceMethod < ClassMethod
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/is_a.rb b/vendor/gems/mocha-0.5.6/lib/mocha/is_a.rb
new file mode 100644
index 0000000..ee23c86
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/is_a.rb
@@ -0,0 +1,9 @@
+class Object
+
+  # :stopdoc:
+
+  alias_method :__is_a__, :is_a?
+
+  # :startdoc:
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/metaclass.rb b/vendor/gems/mocha-0.5.6/lib/mocha/metaclass.rb
new file mode 100644
index 0000000..f78fb89
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/metaclass.rb
@@ -0,0 +1,7 @@
+class Object
+  
+  def __metaclass__
+    class << self; self; end
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/method_matcher.rb b/vendor/gems/mocha-0.5.6/lib/mocha/method_matcher.rb
new file mode 100644
index 0000000..6ce5f6d
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/method_matcher.rb
@@ -0,0 +1,21 @@
+module Mocha
+  
+  class MethodMatcher
+    
+    attr_reader :expected_method_name
+    
+    def initialize(expected_method_name)
+      @expected_method_name = expected_method_name
+    end
+    
+    def match?(actual_method_name)
+      @expected_method_name == actual_method_name
+    end
+    
+    def mocha_inspect
+      "#{@expected_method_name}"
+    end
+    
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/missing_expectation.rb b/vendor/gems/mocha-0.5.6/lib/mocha/missing_expectation.rb
new file mode 100644
index 0000000..ccff6bf
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/missing_expectation.rb
@@ -0,0 +1,17 @@
+require 'mocha/expectation'
+
+module Mocha # :nodoc:
+  
+  class MissingExpectation < Expectation # :nodoc:
+
+    def verify
+      message = error_message(0, 1)
+      similar_expectations = @mock.expectations.similar(@method_matcher.expected_method_name)
+      method_signatures = similar_expectations.map { |expectation| expectation.method_signature }
+      message << "\nSimilar expectations:\n#{method_signatures.join("\n")}" unless method_signatures.empty?
+      raise ExpectationError.new(message, backtrace)
+    end
+
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/mock.rb b/vendor/gems/mocha-0.5.6/lib/mocha/mock.rb
new file mode 100644
index 0000000..59193e7
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/mock.rb
@@ -0,0 +1,202 @@
+require 'mocha/expectation'
+require 'mocha/expectation_list'
+require 'mocha/stub'
+require 'mocha/missing_expectation'
+require 'mocha/metaclass'
+
+module Mocha # :nodoc:
+  
+  # Traditional mock object.
+  #
+  # Methods return an Expectation which can be further modified by methods on Expectation.
+  class Mock
+    
+    # :call-seq: expects(method_name) -> expectation
+    #            expects(method_names) -> last expectation
+    #
+    # Adds an expectation that a method identified by +method_name+ symbol must be called exactly once with any parameters.
+    # Returns the new expectation which can be further modified by methods on Expectation.
+    #   object = mock()
+    #   object.expects(:method1)
+    #   object.method1
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method1)
+    #   # error raised, because method1 not called exactly once
+    # If +method_names+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+    #   object = mock()
+    #   object.expects(:method1 => :result1, :method2 => :result2)
+    #
+    #   # exactly equivalent to
+    #
+    #   object = mock()
+    #   object.expects(:method1).returns(:result1)
+    #   object.expects(:method2).returns(:result2)
+    #
+    # Aliased by <tt>\_\_expects\_\_</tt>
+    def expects(method_name_or_hash, backtrace = nil)
+      if method_name_or_hash.is_a?(Hash) then
+        method_name_or_hash.each do |method_name, return_value|
+          ensure_method_not_already_defined(method_name)
+          @expectations.add(Expectation.new(self, method_name, backtrace).returns(return_value))
+        end
+      else
+        ensure_method_not_already_defined(method_name_or_hash)
+        @expectations.add(Expectation.new(self, method_name_or_hash, backtrace))
+      end
+    end
+    
+    # :call-seq: stubs(method_name) -> expectation
+    #            stubs(method_names) -> last expectation
+    #
+    # Adds an expectation that a method identified by +method_name+ symbol may be called any number of times with any parameters.
+    # Returns the new expectation which can be further modified by methods on Expectation.
+    #   object = mock()
+    #   object.stubs(:method1)
+    #   object.method1
+    #   object.method1
+    #   # no error raised
+    # If +method_names+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+    #   object = mock()
+    #   object.stubs(:method1 => :result1, :method2 => :result2)
+    #
+    #   # exactly equivalent to
+    #
+    #   object = mock()
+    #   object.stubs(:method1).returns(:result1)
+    #   object.stubs(:method2).returns(:result2)
+    #
+    # Aliased by <tt>\_\_stubs\_\_</tt>
+    def stubs(method_name_or_hash, backtrace = nil)
+      if method_name_or_hash.is_a?(Hash) then
+        method_name_or_hash.each do |method_name, return_value|
+          ensure_method_not_already_defined(method_name)
+          @expectations.add(Stub.new(self, method_name, backtrace).returns(return_value))
+        end
+      else
+        ensure_method_not_already_defined(method_name_or_hash)
+        @expectations.add(Stub.new(self, method_name_or_hash, backtrace))
+      end
+    end
+    
+    # :call-seq: responds_like(responder) -> mock
+    #
+    # Constrains the +mock+ so that it can only expect or stub methods to which +responder+ responds. The constraint is only applied at method invocation time.
+    #
+    # A +NoMethodError+ will be raised if the +responder+ does not <tt>respond_to?</tt> a method invocation (even if the method has been expected or stubbed).
+    #
+    # The +mock+ will delegate its <tt>respond_to?</tt> method to the +responder+.
+    #   class Sheep
+    #     def chew(grass); end
+    #     def self.number_of_legs; end
+    #   end
+    #
+    #   sheep = mock('sheep')
+    #   sheep.expects(:chew)
+    #   sheep.expects(:foo)
+    #   sheep.respond_to?(:chew) # => true
+    #   sheep.respond_to?(:foo) # => true
+    #   sheep.chew
+    #   sheep.foo
+    #   # no error raised
+    #
+    #   sheep = mock('sheep')
+    #   sheep.responds_like(Sheep.new)
+    #   sheep.expects(:chew)
+    #   sheep.expects(:foo)
+    #   sheep.respond_to?(:chew) # => true
+    #   sheep.respond_to?(:foo) # => false
+    #   sheep.chew
+    #   sheep.foo # => raises NoMethodError exception
+    #
+    #   sheep_class = mock('sheep_class')
+    #   sheep_class.responds_like(Sheep)
+    #   sheep_class.stubs(:number_of_legs).returns(4)
+    #   sheep_class.expects(:foo)
+    #   sheep_class.respond_to?(:number_of_legs) # => true
+    #   sheep_class.respond_to?(:foo) # => false
+    #   assert_equal 4, sheep_class.number_of_legs
+    #   sheep_class.foo # => raises NoMethodError exception
+    #
+    # Aliased by +quacks_like+
+    def responds_like(object)
+      @responder = object
+      self
+    end
+    
+    # :stopdoc:
+    
+    def initialize(name = nil, &block)
+      @mock_name = name
+      @expectations = ExpectationList.new
+      @everything_stubbed = false
+      @responder = nil
+      instance_eval(&block) if block
+    end
+
+    attr_reader :everything_stubbed, :expectations
+
+    alias_method :__expects__, :expects
+
+    alias_method :__stubs__, :stubs
+    
+    alias_method :quacks_like, :responds_like
+
+    def add_expectation(expectation)
+      @expectations.add(expectation)
+    end
+    
+    def stub_everything
+      @everything_stubbed = true
+    end
+    
+    def method_missing(symbol, *arguments, &block)
+      if @responder and not @responder.respond_to?(symbol)
+        raise NoMethodError, "undefined method `#{symbol}' for #{self.mocha_inspect} which responds like #{@responder.mocha_inspect}"
+      end
+      matching_expectation = @expectations.detect(symbol, *arguments)
+      if matching_expectation then
+        matching_expectation.invoke(&block)
+      elsif @everything_stubbed then
+        return
+      else
+        unexpected_method_called(symbol, *arguments)
+      end
+    end
+    
+    def respond_to?(symbol)
+      if @responder then
+        @responder.respond_to?(symbol)
+      else
+        @expectations.matches_method?(symbol)
+      end
+    end
+  
+    def unexpected_method_called(symbol, *arguments)
+      MissingExpectation.new(self, symbol).with(*arguments).verify
+    end
+  
+    def verify(&block)
+      @expectations.verify(&block)
+    end
+  
+    def mocha_inspect
+      address = self.__id__ * 2
+      address += 0x100000000 if address < 0
+      @mock_name ? "#<Mock:#{@mock_name}>" : "#<Mock:0x#{'%x' % address}>"
+    end
+    
+    def inspect
+      mocha_inspect
+    end
+    
+    def ensure_method_not_already_defined(method_name)
+      self.__metaclass__.send(:undef_method, method_name) if self.__metaclass__.method_defined?(method_name)
+    end
+
+    # :startdoc:
+
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/multiple_yields.rb b/vendor/gems/mocha-0.5.6/lib/mocha/multiple_yields.rb
new file mode 100644
index 0000000..8186c30
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/multiple_yields.rb
@@ -0,0 +1,20 @@
+module Mocha # :nodoc:
+  
+  class MultipleYields # :nodoc:
+    
+    attr_reader :parameter_groups
+    
+    def initialize(*parameter_groups)
+      @parameter_groups = parameter_groups
+    end
+    
+    def each
+      @parameter_groups.each do |parameter_group|
+        yield(parameter_group)
+      end
+    end
+    
+  end
+  
+end
+    
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/no_yields.rb b/vendor/gems/mocha-0.5.6/lib/mocha/no_yields.rb
new file mode 100644
index 0000000..b0fba41
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/no_yields.rb
@@ -0,0 +1,11 @@
+module Mocha # :nodoc:
+  
+  class NoYields # :nodoc:
+    
+    def each
+    end
+    
+  end
+  
+end
+    
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/object.rb b/vendor/gems/mocha-0.5.6/lib/mocha/object.rb
new file mode 100644
index 0000000..7ccdbad
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/object.rb
@@ -0,0 +1,110 @@
+require 'mocha/mock'
+require 'mocha/instance_method'
+require 'mocha/class_method'
+require 'mocha/any_instance_method'
+
+# Methods added all objects to allow mocking and stubbing on real objects.
+#
+# Methods return a Mocha::Expectation which can be further modified by methods on Mocha::Expectation.
+class Object
+  
+  def mocha # :nodoc:
+    @mocha ||= Mocha::Mock.new
+  end
+  
+  def reset_mocha # :nodoc:
+    @mocha = nil
+  end
+  
+  def stubba_method # :nodoc:
+    Mocha::InstanceMethod
+  end
+  
+  def stubba_object # :nodoc:
+    self
+  end
+  
+  # :call-seq: expects(symbol) -> expectation
+  #
+  # Adds an expectation that a method identified by +symbol+ must be called exactly once with any parameters.
+  # Returns the new expectation which can be further modified by methods on Mocha::Expectation.
+  #   product = Product.new
+  #   product.expects(:save).returns(true)
+  #   assert_equal false, product.save
+  #
+  # The original implementation of <tt>Product#save</tt> is replaced temporarily.
+  #
+  # The original implementation of <tt>Product#save</tt> is restored at the end of the test.
+  def expects(symbol) 
+    method = stubba_method.new(stubba_object, symbol)
+    $stubba.stub(method)
+    mocha.expects(symbol, caller)
+  end
+  
+  # :call-seq: stubs(symbol) -> expectation
+  #
+  # Adds an expectation that a method identified by +symbol+ may be called any number of times with any parameters.
+  # Returns the new expectation which can be further modified by methods on Mocha::Expectation.
+  #   product = Product.new
+  #   product.stubs(:save).returns(true)
+  #   assert_equal false, product.save
+  #
+  # The original implementation of <tt>Product#save</tt> is replaced temporarily.
+  #
+  # The original implementation of <tt>Product#save</tt> is restored at the end of the test.
+  def stubs(symbol) 
+    method = stubba_method.new(stubba_object, symbol)
+    $stubba.stub(method)
+    mocha.stubs(symbol, caller)
+  end
+  
+  def verify # :nodoc:
+    mocha.verify
+  end
+  
+end
+
+class Module # :nodoc:
+  
+  def stubba_method
+    Mocha::ClassMethod
+  end
+    
+end
+  
+class Class
+  
+  def stubba_method # :nodoc:
+    Mocha::ClassMethod
+  end
+
+  class AnyInstance # :nodoc:
+    
+    def initialize(klass)
+      @stubba_object = klass
+    end
+    
+    def stubba_method
+      Mocha::AnyInstanceMethod
+    end
+    
+    def stubba_object
+      @stubba_object
+    end
+    
+  end
+  
+  # :call-seq: any_instance -> mock object
+  #
+  # Returns a mock object which will detect calls to any instance of this class.
+  #   Product.any_instance.stubs(:save).returns(false)
+  #   product_1 = Product.new
+  #   assert_equal false, product_1.save
+  #   product_2 = Product.new
+  #   assert_equal false, product_2.save
+  def any_instance
+    @any_instance ||= AnyInstance.new(self)
+  end
+  
+end
+
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers.rb
new file mode 100644
index 0000000..a110479
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers.rb
@@ -0,0 +1,25 @@
+module Mocha
+  
+  # Used as parameters for Expectation#with to restrict the parameter values which will match the expectation.
+  module ParameterMatchers; end
+  
+end
+
+require 'mocha/parameter_matchers/object'
+
+require 'mocha/parameter_matchers/all_of'
+require 'mocha/parameter_matchers/any_of'
+require 'mocha/parameter_matchers/any_parameters'
+require 'mocha/parameter_matchers/anything'
+require 'mocha/parameter_matchers/equals'
+require 'mocha/parameter_matchers/has_entry'
+require 'mocha/parameter_matchers/has_entries'
+require 'mocha/parameter_matchers/has_key'
+require 'mocha/parameter_matchers/has_value'
+require 'mocha/parameter_matchers/includes'
+require 'mocha/parameter_matchers/instance_of'
+require 'mocha/parameter_matchers/is_a'
+require 'mocha/parameter_matchers/kind_of'
+require 'mocha/parameter_matchers/not'
+require 'mocha/parameter_matchers/optionally'
+require 'mocha/parameter_matchers/regexp_matches'
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._all_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._all_of.rb
new file mode 100644
index 0000000..41edbb8
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._all_of.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._any_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._any_of.rb
new file mode 100644
index 0000000..ff228f5
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._any_of.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._any_parameters.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._any_parameters.rb
new file mode 100644
index 0000000..7f2968c
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._any_parameters.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._anything.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._anything.rb
new file mode 100644
index 0000000..5efdf54
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._anything.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._base.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._base.rb
new file mode 100644
index 0000000..fc871fd
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._base.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._equals.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._equals.rb
new file mode 100644
index 0000000..c0dfb4c
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._equals.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_entries.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_entries.rb
new file mode 100644
index 0000000..6228584
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_entries.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_entry.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_entry.rb
new file mode 100644
index 0000000..fe7b51c
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_entry.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_key.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_key.rb
new file mode 100644
index 0000000..e045911
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_key.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_value.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_value.rb
new file mode 100644
index 0000000..a9565f2
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._has_value.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._includes.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._includes.rb
new file mode 100644
index 0000000..0139a2d
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._includes.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._instance_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._instance_of.rb
new file mode 100644
index 0000000..718e376
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._instance_of.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._is_a.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._is_a.rb
new file mode 100644
index 0000000..189a411
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._is_a.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._kind_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._kind_of.rb
new file mode 100644
index 0000000..b99d0d7
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._kind_of.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._not.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._not.rb
new file mode 100644
index 0000000..72ad065
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._not.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._object.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._object.rb
new file mode 100644
index 0000000..5b11734
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._object.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._optionally.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._optionally.rb
new file mode 100644
index 0000000..2177fc7
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._optionally.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._regexp_matches.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._regexp_matches.rb
new file mode 100644
index 0000000..2b30b08
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/._regexp_matches.rb differ
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/all_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/all_of.rb
new file mode 100644
index 0000000..369eb43
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/all_of.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: all_of -> parameter_matcher
+    #
+    # Matches if all +matchers+ match.
+    #   object = mock()
+    #   object.expects(:method_1).with(all_of(includes(1), includes(3)))
+    #   object.method_1([1, 3])
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(all_of(includes(1), includes(3)))
+    #   object.method_1([1, 2])
+    #   # error raised, because method_1 was not called with object including 1 and 3
+    def all_of(*matchers)
+      AllOf.new(*matchers)
+    end
+    
+    class AllOf < Base # :nodoc:
+      
+      def initialize(*matchers)
+        @matchers = matchers
+      end
+    
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        @matchers.all? { |matcher| matcher.matches?([parameter]) }
+      end
+      
+      def mocha_inspect
+        "all_of(#{@matchers.map { |matcher| matcher.mocha_inspect }.join(", ") })"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/any_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/any_of.rb
new file mode 100644
index 0000000..dd254b1
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/any_of.rb
@@ -0,0 +1,47 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: any_of -> parameter_matcher
+    #
+    # Matches if any +matchers+ match.
+    #   object = mock()
+    #   object.expects(:method_1).with(any_of(1, 3))
+    #   object.method_1(1)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(any_of(1, 3))
+    #   object.method_1(3)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(any_of(1, 3))
+    #   object.method_1(2)
+    #   # error raised, because method_1 was not called with 1 or 3
+    def any_of(*matchers)
+      AnyOf.new(*matchers)
+    end
+    
+    class AnyOf < Base # :nodoc:
+      
+      def initialize(*matchers)
+        @matchers = matchers
+      end
+    
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        @matchers.any? { |matcher| matcher.matches?([parameter]) }
+      end
+      
+      def mocha_inspect
+        "any_of(#{@matchers.map { |matcher| matcher.mocha_inspect }.join(", ") })"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/any_parameters.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/any_parameters.rb
new file mode 100644
index 0000000..11dae83
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/any_parameters.rb
@@ -0,0 +1,40 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: any_parameters() -> parameter_matcher
+    #
+    # Matches any parameters.
+    #   object = mock()
+    #   object.expects(:method_1).with(any_parameters)
+    #   object.method_1(1, 2, 3, 4)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(any_parameters)
+    #   object.method_1(5, 6, 7, 8, 9, 0)
+    #   # no error raised
+    def any_parameters
+      AnyParameters.new
+    end
+
+    class AnyParameters < Base # :nodoc:
+      
+      def matches?(available_parameters)
+        while available_parameters.length > 0 do
+          available_parameters.shift
+        end
+        return true
+      end
+
+      def mocha_inspect
+        "any_parameters"
+      end
+
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/anything.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/anything.rb
new file mode 100644
index 0000000..e82ef86
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/anything.rb
@@ -0,0 +1,33 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: anything -> parameter_matcher
+    #
+    # Matches any object.
+    #   object = mock()
+    #   object.expects(:method_1).with(anything)
+    #   object.method_1('foo')
+    #   # no error raised
+    def anything
+      Anything.new
+    end
+    
+    class Anything < Base # :nodoc:
+    
+      def matches?(available_parameters)
+        available_parameters.shift
+        return true
+      end
+      
+      def mocha_inspect
+        "anything"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/base.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/base.rb
new file mode 100644
index 0000000..6aaec51
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/base.rb
@@ -0,0 +1,15 @@
+module Mocha
+  
+  module ParameterMatchers
+    
+    class Base # :nodoc:
+      
+      def to_matcher
+        self
+      end
+      
+    end
+    
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/equals.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/equals.rb
new file mode 100644
index 0000000..bdc61a0
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/equals.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: equals(value) -> parameter_matcher
+    #
+    # Matches +Object+ equalling +value+.
+    #   object = mock()
+    #   object.expects(:method_1).with(equals(2))
+    #   object.method_1(2)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(equals(2))
+    #   object.method_1(3)
+    #   # error raised, because method_1 was not called with Object equalling 3
+    def equals(value)
+      Equals.new(value)
+    end
+
+    class Equals < Base # :nodoc:
+      
+      def initialize(value)
+        @value = value
+      end
+      
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter == @value
+      end
+      
+      def mocha_inspect
+        @value.mocha_inspect
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_entries.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_entries.rb
new file mode 100644
index 0000000..30cf025
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_entries.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: has_entries(entries) -> parameter_matcher
+    #
+    # Matches +Hash+ containing all +entries+.
+    #   object = mock()
+    #   object.expects(:method_1).with(has_entries('key_1' => 1, 'key_2' => 2))
+    #   object.method_1('key_1' => 1, 'key_2' => 2, 'key_3' => 3)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(has_entries('key_1' => 1, 'key_2' => 2))
+    #   object.method_1('key_1' => 1, 'key_2' => 99)
+    #   # error raised, because method_1 was not called with Hash containing entries: 'key_1' => 1, 'key_2' => 2
+    def has_entries(entries)
+      HasEntries.new(entries)
+    end
+    
+    class HasEntries < Base # :nodoc:
+      
+      def initialize(entries)
+        @entries = entries
+      end
+      
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        @entries.all? { |key, value| parameter[key] == value }
+      end
+      
+      def mocha_inspect
+        "has_entries(#{@entries.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_entry.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_entry.rb
new file mode 100644
index 0000000..b645961
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_entry.rb
@@ -0,0 +1,55 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: has_entry(key, value) -> parameter_matcher
+    #            has_entry(key => value) -> parameter_matcher
+    #
+    # Matches +Hash+ containing entry with +key+ and +value+.
+    #   object = mock()
+    #   object.expects(:method_1).with(has_entry('key_1', 1))
+    #   object.method_1('key_1' => 1, 'key_2' => 2)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(has_entry('key_1' => 1))
+    #   object.method_1('key_1' => 1, 'key_2' => 2)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(has_entry('key_1', 1))
+    #   object.method_1('key_1' => 2, 'key_2' => 1)
+    #   # error raised, because method_1 was not called with Hash containing entry: 'key_1' => 1
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(has_entry('key_1' => 1))
+    #   object.method_1('key_1' => 2, 'key_2' => 1)
+    #   # error raised, because method_1 was not called with Hash containing entry: 'key_1' => 1
+    def has_entry(*options)
+      key, value = options.shift, options.shift
+      key, value = key.to_a[0][0..1] if key.is_a?(Hash)
+      HasEntry.new(key, value)
+    end
+    
+    class HasEntry < Base # :nodoc:
+      
+      def initialize(key, value)
+        @key, @value = key, value
+      end
+      
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter[@key] == @value
+      end
+      
+      def mocha_inspect
+        "has_entry(#{@key.mocha_inspect}, #{@value.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_key.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_key.rb
new file mode 100644
index 0000000..2478152
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_key.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: has_key(key) -> parameter_matcher
+    #
+    # Matches +Hash+ containing +key+.
+    #   object = mock()
+    #   object.expects(:method_1).with(has_key('key_1'))
+    #   object.method_1('key_1' => 1, 'key_2' => 2)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(has_key('key_1'))
+    #   object.method_1('key_2' => 2)
+    #   # error raised, because method_1 was not called with Hash containing key: 'key_1'
+    def has_key(key)
+      HasKey.new(key)
+    end
+
+    class HasKey < Base # :nodoc:
+      
+      def initialize(key)
+        @key = key
+      end
+      
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter.keys.include?(@key)
+      end
+      
+      def mocha_inspect
+        "has_key(#{@key.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_value.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_value.rb
new file mode 100644
index 0000000..2c6fe7c
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/has_value.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: has_value(value) -> parameter_matcher
+    #
+    # Matches +Hash+ containing +value+.
+    #   object = mock()
+    #   object.expects(:method_1).with(has_value(1))
+    #   object.method_1('key_1' => 1, 'key_2' => 2)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(has_value(1))
+    #   object.method_1('key_2' => 2)
+    #   # error raised, because method_1 was not called with Hash containing value: 1
+    def has_value(value)
+      HasValue.new(value)
+    end
+
+    class HasValue < Base # :nodoc:
+      
+      def initialize(value)
+        @value = value
+      end
+      
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter.values.include?(@value)
+      end
+      
+      def mocha_inspect
+        "has_value(#{@value.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/includes.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/includes.rb
new file mode 100644
index 0000000..4539a5c
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/includes.rb
@@ -0,0 +1,40 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: includes(item) -> parameter_matcher
+    #
+    # Matches any object that responds true to include?(item)
+    #   object = mock()
+    #   object.expects(:method_1).with(includes('foo'))
+    #   object.method_1(['foo', 'bar'])
+    #   # no error raised
+    #
+    #   object.method_1(['baz'])
+    #   # error raised, because ['baz'] does not include 'foo'.
+    def includes(item)
+      Includes.new(item)
+    end
+
+    class Includes < Base # :nodoc:
+
+      def initialize(item)
+        @item = item
+      end
+
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        return parameter.include?(@item)
+      end
+
+      def mocha_inspect
+        "includes(#{@item.mocha_inspect})"
+      end
+
+    end
+
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/instance_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/instance_of.rb
new file mode 100644
index 0000000..49b4a47
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/instance_of.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: instance_of(klass) -> parameter_matcher
+    #
+    # Matches any object that is an instance of +klass+
+    #   object = mock()
+    #   object.expects(:method_1).with(instance_of(String))
+    #   object.method_1('string')
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(instance_of(String))
+    #   object.method_1(99)
+    #   # error raised, because method_1 was not called with an instance of String
+    def instance_of(klass)
+      InstanceOf.new(klass)
+    end
+    
+    class InstanceOf < Base # :nodoc:
+      
+      def initialize(klass)
+        @klass = klass
+      end
+    
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter.instance_of?(@klass)
+      end
+      
+      def mocha_inspect
+        "instance_of(#{@klass.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/is_a.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/is_a.rb
new file mode 100644
index 0000000..a721db5
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/is_a.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: is_a(klass) -> parameter_matcher
+    #
+    # Matches any object that is a +klass+
+    #   object = mock()
+    #   object.expects(:method_1).with(is_a(Integer))
+    #   object.method_1(99)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(is_a(Integer))
+    #   object.method_1('string')
+    #   # error raised, because method_1 was not called with an Integer
+    def is_a(klass)
+      IsA.new(klass)
+    end
+    
+    class IsA < Base # :nodoc:
+      
+      def initialize(klass)
+        @klass = klass
+      end
+    
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter.is_a?(@klass)
+      end
+      
+      def mocha_inspect
+        "is_a(#{@klass.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/kind_of.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/kind_of.rb
new file mode 100644
index 0000000..710d709
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/kind_of.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: kind_of(klass) -> parameter_matcher
+    #
+    # Matches any object that is a kind of +klass+
+    #   object = mock()
+    #   object.expects(:method_1).with(kind_of(Integer))
+    #   object.method_1(99)
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(kind_of(Integer))
+    #   object.method_1('string')
+    #   # error raised, because method_1 was not called with a kind of Integer
+    def kind_of(klass)
+      KindOf.new(klass)
+    end
+    
+    class KindOf < Base # :nodoc:
+      
+      def initialize(klass)
+        @klass = klass
+      end
+    
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter.kind_of?(@klass)
+      end
+      
+      def mocha_inspect
+        "kind_of(#{@klass.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/not.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/not.rb
new file mode 100644
index 0000000..ec48ade
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/not.rb
@@ -0,0 +1,42 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: Not(matcher) -> parameter_matcher
+    #
+    # Matches if +matcher+ does not match.
+    #   object = mock()
+    #   object.expects(:method_1).with(Not(includes(1)))
+    #   object.method_1([0, 2, 3])
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(Not(includes(1)))
+    #   object.method_1([0, 1, 2, 3])
+    #   # error raised, because method_1 was not called with object not including 1
+    def Not(matcher)
+      Not.new(matcher)
+    end
+    
+    class Not < Base # :nodoc:
+      
+      def initialize(matcher)
+        @matcher = matcher
+      end
+    
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        !@matcher.matches?([parameter])
+      end
+      
+      def mocha_inspect
+        "Not(#{@matcher.mocha_inspect})"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/object.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/object.rb
new file mode 100644
index 0000000..f3a639b
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/object.rb
@@ -0,0 +1,9 @@
+require 'mocha/parameter_matchers/equals'
+
+class Object
+  
+  def to_matcher
+    Mocha::ParameterMatchers::Equals.new(self)
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/optionally.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/optionally.rb
new file mode 100644
index 0000000..bb96251
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/optionally.rb
@@ -0,0 +1,33 @@
+module Mocha
+  
+  module ParameterMatchers
+
+    def optionally(*matchers)
+      Optionally.new(*matchers)
+    end
+    
+    class Optionally < Base # :nodoc:
+      
+      def initialize(*parameters)
+        @matchers = parameters.map { |parameter| parameter.to_matcher }
+      end
+      
+      def matches?(available_parameters)
+        index = 0
+        while (available_parameters.length > 0) && (index < @matchers.length) do
+          matcher = @matchers[index]
+          return false unless matcher.matches?(available_parameters)
+          index += 1
+        end
+        return true
+      end
+      
+      def mocha_inspect
+        "optionally(#{@matchers.map { |matcher| matcher.mocha_inspect }.join(", ") })"
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/regexp_matches.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/regexp_matches.rb
new file mode 100644
index 0000000..cc46436
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameter_matchers/regexp_matches.rb
@@ -0,0 +1,43 @@
+require 'mocha/parameter_matchers/base'
+
+module Mocha
+  
+  module ParameterMatchers
+
+    # :call-seq: regexp_matches(regexp) -> parameter_matcher
+    #
+    # Matches any object that matches the regular expression, +regexp+.
+    #   object = mock()
+    #   object.expects(:method_1).with(regexp_matches(/e/))
+    #   object.method_1('hello')
+    #   # no error raised
+    #
+    #   object = mock()
+    #   object.expects(:method_1).with(regexp_matches(/a/))
+    #   object.method_1('hello')
+    #   # error raised, because method_1 was not called with a parameter that matched the 
+    #   # regular expression
+    def regexp_matches(regexp)
+      RegexpMatches.new(regexp)
+    end
+
+    class RegexpMatches < Base # :nodoc:
+  
+      def initialize(regexp)
+        @regexp = regexp
+      end
+  
+      def matches?(available_parameters)
+        parameter = available_parameters.shift
+        parameter =~ @regexp
+      end
+  
+      def mocha_inspect
+        "regexp_matches(#{@regexp.mocha_inspect})"
+      end
+  
+    end
+    
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/parameters_matcher.rb b/vendor/gems/mocha-0.5.6/lib/mocha/parameters_matcher.rb
new file mode 100644
index 0000000..d43ae43
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/parameters_matcher.rb
@@ -0,0 +1,37 @@
+require 'mocha/inspect'
+require 'mocha/parameter_matchers'
+
+module Mocha
+  
+  class ParametersMatcher
+    
+    def initialize(expected_parameters = [ParameterMatchers::AnyParameters.new], &matching_block)
+      @expected_parameters, @matching_block = expected_parameters, matching_block
+    end
+    
+    def match?(actual_parameters = [])
+      if @matching_block
+        return @matching_block.call(*actual_parameters)
+      else
+        return parameters_match?(actual_parameters)
+      end
+    end
+    
+    def parameters_match?(actual_parameters)
+      matchers.all? { |matcher| matcher.matches?(actual_parameters) } && (actual_parameters.length == 0)
+    end
+    
+    def mocha_inspect
+      signature = matchers.mocha_inspect
+      signature = signature.gsub(/^\[|\]$/, '')
+      signature = signature.gsub(/^\{|\}$/, '') if matchers.length == 1
+      "(#{signature})"
+    end
+    
+    def matchers
+      @expected_parameters.map { |parameter| parameter.to_matcher }
+    end
+    
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/pretty_parameters.rb b/vendor/gems/mocha-0.5.6/lib/mocha/pretty_parameters.rb
new file mode 100644
index 0000000..59ed636
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/pretty_parameters.rb
@@ -0,0 +1,28 @@
+require 'mocha/inspect'
+
+module Mocha
+
+  class PrettyParameters
+  
+    def initialize(params)
+      @params = params
+      @params_string = params.mocha_inspect
+    end
+  
+    def pretty
+      remove_outer_array_braces!
+      remove_outer_hash_braces!
+      @params_string
+    end
+  
+    def remove_outer_array_braces!
+      @params_string = @params_string.gsub(/^\[|\]$/, '')
+    end
+  
+    def remove_outer_hash_braces!
+      @params_string = @params_string.gsub(/^\{|\}$/, '') if @params.length == 1
+    end
+  
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/return_values.rb b/vendor/gems/mocha-0.5.6/lib/mocha/return_values.rb
new file mode 100644
index 0000000..b4852c5
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/return_values.rb
@@ -0,0 +1,34 @@
+require 'mocha/single_return_value'
+
+module Mocha # :nodoc:
+  
+  class ReturnValues # :nodoc:
+    
+    def self.build(*values)
+      new(*values.map { |value| SingleReturnValue.new(value) })
+    end
+    
+    attr_accessor :values
+    
+    def initialize(*values)
+      @values = values
+    end
+    
+    def next
+      case @values.length
+        when 0
+          nil
+        when 1
+          @values.first.evaluate
+        else
+          @values.shift.evaluate
+      end
+    end
+    
+    def +(other)
+      self.class.new(*(@values + other.values))
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/sequence.rb b/vendor/gems/mocha-0.5.6/lib/mocha/sequence.rb
new file mode 100644
index 0000000..ed9852e
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/sequence.rb
@@ -0,0 +1,42 @@
+module Mocha # :nodoc:
+  
+  class Sequence
+    
+    class InSequenceOrderingConstraint
+      
+      def initialize(sequence, index)
+        @sequence, @index = sequence, index
+      end
+      
+      def allows_invocation_now?
+        @sequence.satisfied_to_index?(@index)
+      end
+      
+      def mocha_inspect
+        "in sequence #{@sequence.mocha_inspect}"
+      end
+      
+    end
+    
+    def initialize(name)
+      @name = name
+      @expectations = []
+    end
+    
+    def constrain_as_next_in_sequence(expectation)
+      index = @expectations.length
+      @expectations << expectation
+      expectation.add_ordering_constraint(InSequenceOrderingConstraint.new(self, index))
+    end
+    
+    def satisfied_to_index?(index)
+      @expectations[0...index].all? { |expectation| expectation.satisfied? }
+    end
+    
+    def mocha_inspect
+      "#{@name.mocha_inspect}"
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/setup_and_teardown.rb b/vendor/gems/mocha-0.5.6/lib/mocha/setup_and_teardown.rb
new file mode 100644
index 0000000..034ce1d
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/setup_and_teardown.rb
@@ -0,0 +1,23 @@
+require 'mocha/central'
+
+module Mocha
+  
+  module SetupAndTeardown
+  
+    def setup_stubs
+      $stubba = Mocha::Central.new
+    end
+    
+    def verify_stubs
+      $stubba.verify_all { yield if block_given? } if $stubba
+    end
+  
+    def teardown_stubs
+      if $stubba then
+        $stubba.unstub_all
+        $stubba = nil
+      end
+    end
+
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/single_return_value.rb b/vendor/gems/mocha-0.5.6/lib/mocha/single_return_value.rb
new file mode 100644
index 0000000..f420b8b
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/single_return_value.rb
@@ -0,0 +1,24 @@
+require 'mocha/is_a'
+require 'mocha/deprecation'
+
+module Mocha # :nodoc:
+  
+  class SingleReturnValue # :nodoc:
+    
+    def initialize(value)
+      @value = value
+    end
+    
+    def evaluate
+      if @value.__is_a__(Proc) then
+        message = 'use of Expectation#returns with instance of Proc - see Expectation#returns RDoc for alternatives'
+        Deprecation.warning(message)
+        @value.call
+      else
+        @value
+      end
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/single_yield.rb b/vendor/gems/mocha-0.5.6/lib/mocha/single_yield.rb
new file mode 100644
index 0000000..5af5716
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/single_yield.rb
@@ -0,0 +1,18 @@
+module Mocha # :nodoc:
+  
+  class SingleYield # :nodoc:
+    
+    attr_reader :parameters
+    
+    def initialize(*parameters)
+      @parameters = parameters
+    end
+    
+    def each
+      yield(@parameters)
+    end
+    
+  end
+  
+end
+    
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/standalone.rb b/vendor/gems/mocha-0.5.6/lib/mocha/standalone.rb
new file mode 100644
index 0000000..8e3a7ce
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/standalone.rb
@@ -0,0 +1,32 @@
+require 'mocha/auto_verify'
+require 'mocha/parameter_matchers'
+require 'mocha/setup_and_teardown'
+
+module Mocha
+  
+  module Standalone
+    
+    include AutoVerify
+    include ParameterMatchers
+    include SetupAndTeardown
+    
+    def mocha_setup
+      setup_stubs
+    end
+    
+    def mocha_verify(&block)
+      verify_mocks(&block)
+      verify_stubs(&block)
+    end
+    
+    def mocha_teardown
+      begin
+        teardown_mocks
+      ensure
+        teardown_stubs
+      end
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/stub.rb b/vendor/gems/mocha-0.5.6/lib/mocha/stub.rb
new file mode 100644
index 0000000..1b3cccb
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/stub.rb
@@ -0,0 +1,18 @@
+require 'mocha/expectation'
+
+module Mocha # :nodoc:
+
+  class Stub < Expectation # :nodoc:
+
+    def initialize(mock, method_name, backtrace = nil)
+      super
+      @expected_count = Range.at_least(0)
+    end
+    
+    def verify
+      true
+    end
+
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/test_case_adapter.rb b/vendor/gems/mocha-0.5.6/lib/mocha/test_case_adapter.rb
new file mode 100644
index 0000000..dc7e33b
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/test_case_adapter.rb
@@ -0,0 +1,49 @@
+require 'mocha/expectation_error'
+
+module Mocha
+  
+  module TestCaseAdapter
+
+    def self.included(base)
+      base.class_eval do
+
+        alias_method :run_before_mocha_test_case_adapter, :run
+
+        def run(result)
+          yield(Test::Unit::TestCase::STARTED, name)
+          @_result = result
+          begin
+            mocha_setup
+            begin
+              setup
+              __send__(@method_name)
+              mocha_verify { add_assertion }
+            rescue Mocha::ExpectationError => e
+              add_failure(e.message, e.backtrace)
+            rescue Test::Unit::AssertionFailedError => e
+              add_failure(e.message, e.backtrace)
+            rescue StandardError, ScriptError
+              add_error($!)
+            ensure
+              begin
+                teardown
+              rescue Test::Unit::AssertionFailedError => e
+                add_failure(e.message, e.backtrace)
+              rescue StandardError, ScriptError
+                add_error($!)
+              end
+            end
+          ensure
+            mocha_teardown
+          end
+          result.add_run
+          yield(Test::Unit::TestCase::FINISHED, name)
+        end
+                
+      end
+      
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/lib/mocha/yield_parameters.rb b/vendor/gems/mocha-0.5.6/lib/mocha/yield_parameters.rb
new file mode 100644
index 0000000..cb58985
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/mocha/yield_parameters.rb
@@ -0,0 +1,31 @@
+require 'mocha/no_yields'
+require 'mocha/single_yield'
+require 'mocha/multiple_yields'
+
+module Mocha # :nodoc:
+  
+  class YieldParameters # :nodoc:
+    
+    def initialize
+      @parameter_groups = []
+    end
+    
+    def next_invocation
+      case @parameter_groups.length
+      when 0; NoYields.new
+      when 1; @parameter_groups.first
+      else @parameter_groups.shift
+      end
+    end
+    
+    def add(*parameters)
+      @parameter_groups << SingleYield.new(*parameters)
+    end
+    
+    def multiple_add(*parameter_groups)
+      @parameter_groups << MultipleYields.new(*parameter_groups)
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/test/lib/mocha_standalone.rb b/vendor/gems/mocha-0.5.6/lib/mocha_standalone.rb
similarity index 100%
copy from test/lib/mocha_standalone.rb
copy to vendor/gems/mocha-0.5.6/lib/mocha_standalone.rb
diff --git a/vendor/gems/mocha-0.5.6/lib/stubba.rb b/vendor/gems/mocha-0.5.6/lib/stubba.rb
new file mode 100644
index 0000000..eade747
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/lib/stubba.rb
@@ -0,0 +1,2 @@
+# for backwards compatibility
+require 'mocha'
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/._deprecation_disabler.rb b/vendor/gems/mocha-0.5.6/test/._deprecation_disabler.rb
new file mode 100644
index 0000000..64a1d06
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/._deprecation_disabler.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/._execution_point.rb b/vendor/gems/mocha-0.5.6/test/._execution_point.rb
new file mode 100644
index 0000000..dd624fd
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/._execution_point.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/._method_definer.rb b/vendor/gems/mocha-0.5.6/test/._method_definer.rb
new file mode 100644
index 0000000..d51c1ad
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/._method_definer.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/._test_helper.rb b/vendor/gems/mocha-0.5.6/test/._test_helper.rb
new file mode 100644
index 0000000..ef386d5
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/._test_helper.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/._test_runner.rb b/vendor/gems/mocha-0.5.6/test/._test_runner.rb
new file mode 100644
index 0000000..614cc3f
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/._test_runner.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._expected_invocation_count_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._expected_invocation_count_acceptance_test.rb
new file mode 100644
index 0000000..86e37bd
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._expected_invocation_count_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._mocha_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._mocha_acceptance_test.rb
new file mode 100644
index 0000000..39f36f8
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._mocha_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._mock_with_initializer_block_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._mock_with_initializer_block_acceptance_test.rb
new file mode 100644
index 0000000..8e3a0e7
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._mock_with_initializer_block_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._mocked_methods_dispatch_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._mocked_methods_dispatch_acceptance_test.rb
new file mode 100644
index 0000000..de0671d
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._mocked_methods_dispatch_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._optional_parameters_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._optional_parameters_acceptance_test.rb
new file mode 100644
index 0000000..b21de1f
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._optional_parameters_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._parameter_matcher_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._parameter_matcher_acceptance_test.rb
new file mode 100644
index 0000000..421ef5a
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._parameter_matcher_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._partial_mocks_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._partial_mocks_acceptance_test.rb
new file mode 100644
index 0000000..c565022
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._partial_mocks_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._sequence_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._sequence_acceptance_test.rb
new file mode 100644
index 0000000..8bb33ec
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._sequence_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._standalone_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._standalone_acceptance_test.rb
new file mode 100644
index 0000000..68a7236
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._standalone_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/._stubba_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/._stubba_acceptance_test.rb
new file mode 100644
index 0000000..5140f12
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/acceptance/._stubba_acceptance_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/expected_invocation_count_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/expected_invocation_count_acceptance_test.rb
new file mode 100644
index 0000000..c09168c
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/expected_invocation_count_acceptance_test.rb
@@ -0,0 +1,187 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+require 'test_runner'
+
+class ExpectedInvocationCountAcceptanceTest < Test::Unit::TestCase
+
+  include TestRunner
+
+  def test_should_pass_if_method_is_never_expected_and_is_never_called
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).never
+      0.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_fail_if_method_is_never_expected_but_is_called_once
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).never
+      1.times { mock.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:mock>.method(any_parameters) - expected calls: 0, actual calls: 1'], failure_messages
+  end
+  
+  def test_should_pass_if_method_is_expected_twice_and_is_called_twice
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2)
+      2.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_fail_if_method_is_expected_twice_but_is_called_once
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2)
+      1.times { mock.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:mock>.method(any_parameters) - expected calls: 2, actual calls: 1'], failure_messages
+  end
+  
+  def test_should_fail_if_method_is_expected_twice_but_is_called_three_times
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2)
+      3.times { mock.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:mock>.method(any_parameters) - expected calls: 2, actual calls: 3'], failure_messages
+  end
+  
+  def test_should_pass_if_method_is_expected_between_two_and_four_times_and_is_called_twice
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2..4)
+      2.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_pass_if_method_is_expected_between_two_and_four_times_and_is_called_three_times
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2..4)
+      3.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_pass_if_method_is_expected_between_two_and_four_times_and_is_called_four_times
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2..4)
+      4.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_fail_if_method_is_expected_between_two_and_four_times_and_is_called_once
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2..4)
+      1.times { mock.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:mock>.method(any_parameters) - expected calls: 2..4, actual calls: 1'], failure_messages
+  end
+
+  def test_should_fail_if_method_is_expected_between_two_and_four_times_and_is_called_five_times
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).times(2..4)
+      5.times { mock.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:mock>.method(any_parameters) - expected calls: 2..4, actual calls: 5'], failure_messages
+  end
+  
+  def test_should_pass_if_method_is_expected_at_least_once_and_is_called_once
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).at_least_once
+      1.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_pass_if_method_is_expected_at_least_once_and_is_called_twice
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).at_least_once
+      2.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_fail_if_method_is_expected_at_least_once_but_is_never_called
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).at_least_once
+      0.times { mock.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:mock>.method(any_parameters) - expected calls: at least 1, actual calls: 0'], failure_messages
+  end
+  
+  def test_should_pass_if_method_is_expected_at_most_once_and_is_never_called
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).at_most_once
+      0.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_pass_if_method_is_expected_at_most_once_and_called_once
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).at_most_once
+      1.times { mock.method }
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_fail_if_method_is_expected_at_most_once_but_is_called_twice
+    test_result = run_test do
+      mock = mock('mock')
+      mock.expects(:method).at_most_once
+      2.times { mock.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:mock>.method(any_parameters) - expected calls: at most 1, actual calls: 2'], failure_messages
+  end
+  
+  def test_should_pass_if_method_is_never_expected_and_is_never_called_even_if_everything_is_stubbed
+    test_result = run_test do
+      stub = stub_everything('stub')
+      stub.expects(:method).never
+      0.times { stub.method }
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_fail_if_method_is_never_expected_but_is_called_once_even_if_everything_is_stubbed
+    test_result = run_test do
+      stub = stub_everything('stub')
+      stub.expects(:method).never
+      1.times { stub.method }
+    end
+    assert_failed(test_result)
+    failure_messages = test_result.failures.map { |failure| failure.message }
+    assert_equal ['#<Mock:stub>.method(any_parameters) - expected calls: 0, actual calls: 1'], failure_messages
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/mocha_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/mocha_acceptance_test.rb
new file mode 100644
index 0000000..4e38b4e
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/mocha_acceptance_test.rb
@@ -0,0 +1,98 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+
+class MochaAcceptanceTest < Test::Unit::TestCase
+  
+  class Rover
+
+    def initialize(left_track, right_track, steps_per_metre, steps_per_degree)
+      @left_track, @right_track, @steps_per_metre, @steps_per_degree = left_track, right_track, steps_per_metre, steps_per_degree
+    end
+
+    def forward(metres)
+      @left_track.step(metres * @steps_per_metre)
+      @right_track.step(metres * @steps_per_metre)
+      wait
+    end
+
+    def backward(metres)
+      forward(-metres)
+    end
+    
+    def left(degrees)
+      @left_track.step(-degrees * @steps_per_degree)
+      @right_track.step(+degrees * @steps_per_degree)
+      wait
+    end
+    
+    def right(degrees)
+      left(-degrees)
+    end
+    
+    def wait
+      while (@left_track.moving? or @right_track.moving?); end
+    end
+
+  end
+  
+  def test_should_step_both_tracks_forward_ten_steps
+    left_track = mock('left_track')
+    right_track = mock('right_track')
+    steps_per_metre = 5
+    rover = Rover.new(left_track, right_track, steps_per_metre, nil)
+    
+    left_track.expects(:step).with(10)
+    right_track.expects(:step).with(10)
+    
+    left_track.stubs(:moving?).returns(false)
+    right_track.stubs(:moving?).returns(false)
+    
+    rover.forward(2)
+  end
+  
+  def test_should_step_both_tracks_backward_ten_steps
+    left_track = mock('left_track')
+    right_track = mock('right_track')
+    steps_per_metre = 5
+    rover = Rover.new(left_track, right_track, steps_per_metre, nil)
+    
+    left_track.expects(:step).with(-10)
+    right_track.expects(:step).with(-10)
+    
+    left_track.stubs(:moving?).returns(false)
+    right_track.stubs(:moving?).returns(false)
+    
+    rover.backward(2)
+  end
+  
+  def test_should_step_left_track_forwards_five_steps_and_right_track_backwards_five_steps
+    left_track = mock('left_track')
+    right_track = mock('right_track')
+    steps_per_degree = 5.0 / 90.0
+    rover = Rover.new(left_track, right_track, nil, steps_per_degree)
+    
+    left_track.expects(:step).with(+5)
+    right_track.expects(:step).with(-5)
+    
+    left_track.stubs(:moving?).returns(false)
+    right_track.stubs(:moving?).returns(false)
+    
+    rover.right(90)
+  end
+  
+  def test_should_step_left_track_backwards_five_steps_and_right_track_forwards_five_steps
+    left_track = mock('left_track')
+    right_track = mock('right_track')
+    steps_per_degree = 5.0 / 90.0
+    rover = Rover.new(left_track, right_track, nil, steps_per_degree)
+    
+    left_track.expects(:step).with(-5)
+    right_track.expects(:step).with(+5)
+    
+    left_track.stubs(:moving?).returns(false)
+    right_track.stubs(:moving?).returns(false)
+    
+    rover.left(90)
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/mock_with_initializer_block_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/mock_with_initializer_block_acceptance_test.rb
new file mode 100644
index 0000000..51488e6
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/mock_with_initializer_block_acceptance_test.rb
@@ -0,0 +1,44 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+require 'test_runner'
+
+class MockWithInitializerBlockAcceptanceTest < Test::Unit::TestCase
+  
+  include TestRunner
+
+  def test_should_expect_two_method_invocations_and_receive_both_of_them
+    test_result = run_test do
+      mock = mock() do
+        expects(:method_1)
+        expects(:method_2)
+      end
+      mock.method_1
+      mock.method_2
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_expect_two_method_invocations_but_receive_only_one_of_them
+    test_result = run_test do
+      mock = mock() do
+        expects(:method_1)
+        expects(:method_2)
+      end
+      mock.method_1
+    end
+    assert_failed(test_result)
+  end
+
+  def test_should_stub_methods
+    test_result = run_test do
+      mock = mock() do
+        stubs(:method_1).returns(1)
+        stubs(:method_2).returns(2)
+      end
+      assert_equal 1, mock.method_1
+      assert_equal 2, mock.method_2
+    end
+    assert_passed(test_result)
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/mocked_methods_dispatch_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/mocked_methods_dispatch_acceptance_test.rb
new file mode 100644
index 0000000..d770215
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/mocked_methods_dispatch_acceptance_test.rb
@@ -0,0 +1,71 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+require 'test_runner'
+
+class MockedMethodDispatchAcceptanceTest < Test::Unit::TestCase
+
+  include TestRunner
+
+  def test_should_find_latest_matching_expectation
+    test_result = run_test do
+      mock = mock()
+      mock.stubs(:method).returns(1)
+      mock.stubs(:method).returns(2)
+      assert_equal 2, mock.method
+      assert_equal 2, mock.method
+      assert_equal 2, mock.method
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_find_latest_expectation_which_has_not_stopped_matching
+    test_result = run_test do
+      mock = mock()
+      mock.stubs(:method).returns(1)
+      mock.stubs(:method).once.returns(2)
+      assert_equal 2, mock.method
+      assert_equal 1, mock.method
+      assert_equal 1, mock.method
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_keep_finding_later_stub_and_so_never_satisfy_earlier_expectation
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).returns(1)
+      mock.stubs(:method).returns(2)
+      assert_equal 2, mock.method
+      assert_equal 2, mock.method
+      assert_equal 2, mock.method
+    end
+    assert_failed(test_result)
+  end
+
+  def test_should_find_later_expectation_until_it_stops_matching_then_find_earlier_stub
+    test_result = run_test do
+      mock = mock()
+      mock.stubs(:method).returns(1)
+      mock.expects(:method).returns(2)
+      assert_equal 2, mock.method
+      assert_equal 1, mock.method
+      assert_equal 1, mock.method
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_find_latest_expectation_with_range_of_expected_invocation_count_which_has_not_stopped_matching
+    test_result = run_test do
+      mock = mock()
+      mock.stubs(:method).returns(1)
+      mock.stubs(:method).times(2..3).returns(2)
+      assert_equal 2, mock.method
+      assert_equal 2, mock.method
+      assert_equal 2, mock.method
+      assert_equal 1, mock.method
+      assert_equal 1, mock.method
+    end
+    assert_passed(test_result)
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/optional_parameters_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/optional_parameters_acceptance_test.rb
new file mode 100644
index 0000000..3a6f832
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/optional_parameters_acceptance_test.rb
@@ -0,0 +1,63 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+require 'test_runner'
+
+class OptionalParameterMatcherAcceptanceTest < Test::Unit::TestCase
+  
+  include TestRunner
+  
+  def test_should_pass_if_all_required_parameters_match_and_no_optional_parameters_are_supplied
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(1, 2, optionally(3, 4))
+      mock.method(1, 2)
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_pass_if_all_required_and_optional_parameters_match_and_some_optional_parameters_are_supplied
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(1, 2, optionally(3, 4))
+      mock.method(1, 2, 3)
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_pass_if_all_required_and_optional_parameters_match_and_all_optional_parameters_are_supplied
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(1, 2, optionally(3, 4))
+      mock.method(1, 2, 3, 4)
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_fail_if_all_required_and_optional_parameters_match_but_too_many_optional_parameters_are_supplied
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(1, 2, optionally(3, 4))
+      mock.method(1, 2, 3, 4, 5)
+    end
+    assert_failed(test_result)
+  end
+
+  def test_should_fail_if_all_required_parameters_match_but_some_optional_parameters_do_not_match
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(1, 2, optionally(3, 4))
+      mock.method(1, 2, 4)
+    end
+    assert_failed(test_result)
+  end
+
+  def test_should_fail_if_all_required_parameters_match_but_no_optional_parameters_match
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(1, 2, optionally(3, 4))
+      mock.method(1, 2, 4, 5)
+    end
+    assert_failed(test_result)
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/parameter_matcher_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/parameter_matcher_acceptance_test.rb
new file mode 100644
index 0000000..c23880d
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/parameter_matcher_acceptance_test.rb
@@ -0,0 +1,117 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+require 'test_runner'
+
+class ParameterMatcherAcceptanceTest < Test::Unit::TestCase
+  
+  include TestRunner
+
+  def test_should_match_hash_parameter_with_specified_key
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_key(:key_1))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_2')
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_not_match_hash_parameter_with_specified_key
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_key(:key_1))
+      mock.method(:key_2 => 'value_2')
+    end
+    assert_failed(test_result)
+  end
+  
+  def test_should_match_hash_parameter_with_specified_value
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_value('value_1'))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_2')
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_not_match_hash_parameter_with_specified_value
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_value('value_1'))
+      mock.method(:key_2 => 'value_2')
+    end
+    assert_failed(test_result)
+  end
+  
+  def test_should_match_hash_parameter_with_specified_key_value_pair
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_entry(:key_1, 'value_1'))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_2')
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_not_match_hash_parameter_with_specified_key_value_pair
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_entry(:key_1, 'value_2'))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_2')
+    end
+    assert_failed(test_result)
+  end
+  
+  def test_should_match_hash_parameter_with_specified_hash_entry
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_entry(:key_1 => 'value_1'))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_2')
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_not_match_hash_parameter_with_specified_hash_entry
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_entry(:key_1 => 'value_2'))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_2')
+    end
+    assert_failed(test_result)
+  end
+  
+  def test_should_match_hash_parameter_with_specified_entries
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_entries(:key_1 => 'value_1', :key_2 => 'value_2'))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_2', :key_3 => 'value_3')
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_not_match_hash_parameter_with_specified_entries
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(has_entries(:key_1 => 'value_1', :key_2 => 'value_2'))
+      mock.method(:key_1 => 'value_1', :key_2 => 'value_3')
+    end
+    assert_failed(test_result)
+  end
+  
+  def test_should_match_parameter_that_matches_regular_expression
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(regexp_matches(/meter/))
+      mock.method('this parameter should match')
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_not_match_parameter_that_does_not_match_regular_expression
+    test_result = run_test do
+      mock = mock()
+      mock.expects(:method).with(regexp_matches(/something different/))
+      mock.method('this parameter should not match')
+    end
+    assert_failed(test_result)
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/partial_mocks_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/partial_mocks_acceptance_test.rb
new file mode 100644
index 0000000..20fc7b8
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/partial_mocks_acceptance_test.rb
@@ -0,0 +1,40 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+require 'test_runner'
+
+class PartialMockAcceptanceTest < Test::Unit::TestCase
+  
+  include TestRunner
+
+  def test_should_pass_if_all_expectations_are_satisfied
+    test_result = run_test do
+      partial_mock_one = "partial_mock_one"
+      partial_mock_two = "partial_mock_two"
+      
+      partial_mock_one.expects(:first)
+      partial_mock_one.expects(:second)
+      partial_mock_two.expects(:third)
+      
+      partial_mock_one.first
+      partial_mock_one.second
+      partial_mock_two.third
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_fail_if_all_expectations_are_not_satisfied
+    test_result = run_test do
+      partial_mock_one = "partial_mock_one"
+      partial_mock_two = "partial_mock_two"
+      
+      partial_mock_one.expects(:first)
+      partial_mock_one.expects(:second)
+      partial_mock_two.expects(:third)
+      
+      partial_mock_one.first
+      partial_mock_two.third
+    end
+    assert_failed(test_result)
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/sequence_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/sequence_acceptance_test.rb
new file mode 100644
index 0000000..3be6e7d
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/sequence_acceptance_test.rb
@@ -0,0 +1,179 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+require 'test_runner'
+
+class SequenceAcceptanceTest < Test::Unit::TestCase
+  
+  include TestRunner
+
+  def test_should_constrain_invocations_to_occur_in_expected_order
+    test_result = run_test do
+      mock = mock()
+      sequence = sequence('one')
+      
+      mock.expects(:first).in_sequence(sequence)
+      mock.expects(:second).in_sequence(sequence)
+      
+      mock.second
+    end
+    assert_failed(test_result)
+  end
+
+  def test_should_allow_invocations_in_sequence
+    test_result = run_test do
+      mock = mock()
+      sequence = sequence('one')
+      
+      mock.expects(:first).in_sequence(sequence)
+      mock.expects(:second).in_sequence(sequence)
+      
+      mock.first
+      mock.second
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_constrain_invocations_to_occur_in_expected_order_even_if_expected_on_different_mocks
+    test_result = run_test do
+      mock_one = mock('1')
+      mock_two = mock('2')
+      sequence = sequence('one')
+      
+      mock_one.expects(:first).in_sequence(sequence)
+      mock_two.expects(:second).in_sequence(sequence)
+      
+      mock_two.second
+    end
+    assert_failed(test_result)
+  end
+
+  def test_should_allow_invocations_in_sequence_even_if_expected_on_different_mocks
+    test_result = run_test do
+      mock_one = mock('1')
+      mock_two = mock('2')
+      sequence = sequence('one')
+      
+      mock_one.expects(:first).in_sequence(sequence)
+      mock_two.expects(:second).in_sequence(sequence)
+      
+      mock_one.first
+      mock_two.second
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_constrain_invocations_to_occur_in_expected_order_even_if_expected_on_partial_mocks
+    test_result = run_test do
+      partial_mock_one = "1"
+      partial_mock_two = "2"
+      sequence = sequence('one')
+      
+      partial_mock_one.expects(:first).in_sequence(sequence)
+      partial_mock_two.expects(:second).in_sequence(sequence)
+      
+      partial_mock_two.second
+    end
+    assert_failed(test_result)
+  end
+
+  def test_should_allow_invocations_in_sequence_even_if_expected_on_partial_mocks
+    test_result = run_test do
+      partial_mock_one = "1"
+      partial_mock_two = "2"
+      sequence = sequence('one')
+      
+      partial_mock_one.expects(:first).in_sequence(sequence)
+      partial_mock_two.expects(:second).in_sequence(sequence)
+      
+      partial_mock_one.first
+      partial_mock_two.second
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_allow_stub_expectations_to_be_skipped_in_sequence
+    test_result = run_test do
+      mock = mock()
+      sequence = sequence('one')
+      
+      mock.expects(:first).in_sequence(sequence)
+      s = mock.stubs(:second).in_sequence(sequence)
+      mock.expects(:third).in_sequence(sequence)
+      
+      mock.first
+      mock.third
+    end
+    assert_passed(test_result)
+  end
+
+  def test_should_regard_sequences_as_independent_of_each_other
+    test_result = run_test do
+      mock = mock()
+      sequence_one = sequence('one')
+      sequence_two = sequence('two')
+      
+      mock.expects(:first).in_sequence(sequence_one)
+      mock.expects(:second).in_sequence(sequence_one)
+      
+      mock.expects(:third).in_sequence(sequence_two)
+      mock.expects(:fourth).in_sequence(sequence_two)
+      
+      mock.first
+      mock.third
+      mock.second
+      mock.fourth
+    end
+    assert_passed(test_result)
+  end
+  
+  def test_should_include_sequence_in_failure_message
+    test_result = run_test do
+      mock = mock()
+      sequence = sequence('one')
+      
+      mock.expects(:first).in_sequence(sequence)
+      mock.expects(:second).in_sequence(sequence)
+      
+      mock.second
+    end
+    assert_failed(test_result)
+    assert_match Regexp.new("in sequence 'one'"), test_result.failures.first.message
+  end
+
+  def test_should_allow_expectations_to_be_in_more_than_one_sequence
+    test_result = run_test do
+      mock = mock()
+      sequence_one = sequence('one')
+      sequence_two = sequence('two')
+      
+      mock.expects(:first).in_sequence(sequence_one)
+      mock.expects(:second).in_sequence(sequence_two)
+      mock.expects(:three).in_sequence(sequence_one).in_sequence(sequence_two)
+      
+      mock.first
+      mock.three
+    end
+    assert_failed(test_result)
+    assert_match Regexp.new("in sequence 'one'"), test_result.failures.first.message
+    assert_match Regexp.new("in sequence 'two'"), test_result.failures.first.message
+  end
+
+  def test_should_have_shortcut_for_expectations_to_be_in_more_than_one_sequence
+    test_result = run_test do
+      mock = mock()
+      sequence_one = sequence('one')
+      sequence_two = sequence('two')
+      
+      mock.expects(:first).in_sequence(sequence_one)
+      mock.expects(:second).in_sequence(sequence_two)
+      mock.expects(:three).in_sequence(sequence_one, sequence_two)
+      
+      mock.first
+      mock.three
+    end
+    assert_failed(test_result)
+    assert_match Regexp.new("in sequence 'one'"), test_result.failures.first.message
+    assert_match Regexp.new("in sequence 'two'"), test_result.failures.first.message
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/standalone_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/standalone_acceptance_test.rb
new file mode 100644
index 0000000..1e101d7
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/standalone_acceptance_test.rb
@@ -0,0 +1,131 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha_standalone'
+
+class NotATestUnitAssertionFailedError < StandardError
+end
+
+class NotATestUnitTestCase
+  
+  include Mocha::Standalone
+  
+  attr_reader :assertion_count
+  
+  def initialize
+    @assertion_count = 0
+  end
+  
+  def run(test_method)
+    mocha_setup
+    begin
+      prepare
+      begin
+        send(test_method)
+        mocha_verify { @assertion_count += 1 }
+      rescue Mocha::ExpectationError => e
+        new_error = NotATestUnitAssertionFailedError.new(e.message)
+        new_error.set_backtrace(e.backtrace)
+        raise new_error
+      ensure
+        cleanup
+      end
+    ensure
+      mocha_teardown
+    end
+  end
+  
+  def prepare
+  end
+  
+  def cleanup
+  end
+    
+end
+
+class SampleTest < NotATestUnitTestCase
+  
+  def mocha_with_fulfilled_expectation
+    mockee = mock()
+    mockee.expects(:blah)
+    mockee.blah
+  end
+  
+  def mocha_with_unfulfilled_expectation
+    mockee = mock()
+    mockee.expects(:blah)
+  end
+  
+  def mocha_with_unexpected_invocation
+    mockee = mock()
+    mockee.blah
+  end
+  
+  def stubba_with_fulfilled_expectation
+    stubbee = Class.new { define_method(:blah) {} }.new
+    stubbee.expects(:blah)
+    stubbee.blah
+  end
+  
+  def stubba_with_unfulfilled_expectation
+    stubbee = Class.new { define_method(:blah) {} }.new
+    stubbee.expects(:blah)
+  end
+  
+  def mocha_with_matching_parameter
+    mockee = mock()
+    mockee.expects(:blah).with(has_key(:wibble))
+    mockee.blah(:wibble => 1)
+  end
+  
+  def mocha_with_non_matching_parameter
+    mockee = mock()
+    mockee.expects(:blah).with(has_key(:wibble))
+    mockee.blah(:wobble => 2)
+  end
+  
+end
+
+require 'test/unit'
+
+class StandaloneAcceptanceTest < Test::Unit::TestCase
+  
+  attr_reader :sample_test
+
+  def setup
+    @sample_test = SampleTest.new
+  end
+  
+  def test_should_pass_mocha_test
+    assert_nothing_raised { sample_test.run(:mocha_with_fulfilled_expectation) }
+    assert_equal 1, sample_test.assertion_count
+  end
+
+  def test_should_fail_mocha_test_due_to_unfulfilled_exception
+    assert_raises(NotATestUnitAssertionFailedError) { sample_test.run(:mocha_with_unfulfilled_expectation) }
+    assert_equal 1, sample_test.assertion_count
+  end
+
+  def test_should_fail_mocha_test_due_to_unexpected_invocation
+    assert_raises(NotATestUnitAssertionFailedError) { sample_test.run(:mocha_with_unexpected_invocation) }
+    assert_equal 0, sample_test.assertion_count
+  end
+
+  def test_should_pass_stubba_test
+    assert_nothing_raised { sample_test.run(:stubba_with_fulfilled_expectation) }
+    assert_equal 1, sample_test.assertion_count
+  end
+
+  def test_should_fail_stubba_test
+    assert_raises(NotATestUnitAssertionFailedError) { sample_test.run(:stubba_with_unfulfilled_expectation) }
+    assert_equal 1, sample_test.assertion_count
+  end
+
+  def test_should_pass_mocha_test_with_matching_parameter
+    assert_nothing_raised { sample_test.run(:mocha_with_matching_parameter) }
+    assert_equal 1, sample_test.assertion_count
+  end
+
+  def test_should_fail_mocha_test_with_non_matching_parameter
+    assert_raises(NotATestUnitAssertionFailedError) { sample_test.run(:mocha_with_non_matching_parameter) }
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/acceptance/stubba_acceptance_test.rb b/vendor/gems/mocha-0.5.6/test/acceptance/stubba_acceptance_test.rb
new file mode 100644
index 0000000..93d8d12
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/acceptance/stubba_acceptance_test.rb
@@ -0,0 +1,102 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha'
+
+class Widget
+  
+  def model
+    'original_model'
+  end
+    
+  class << self
+  
+    def find(options)
+      []
+    end
+  
+    def create(attributes)
+      Widget.new
+    end
+  
+  end
+  
+end
+
+module Thingy
+  
+  def self.wotsit
+    :hoojamaflip
+  end
+  
+end
+
+class StubbaAcceptanceTest < Test::Unit::TestCase
+  
+  def test_should_stub_instance_method
+    widget = Widget.new
+    widget.expects(:model).returns('different_model')
+    assert_equal 'different_model', widget.model
+  end
+  
+  def test_should_stub_module_method
+    should_stub_module_method
+  end
+  
+  def test_should_stub_module_method_again
+    should_stub_module_method
+  end
+  
+  def test_should_stub_class_method
+    should_stub_class_method
+  end
+  
+  def test_should_stub_class_method_again
+    should_stub_class_method
+  end
+  
+  def test_should_stub_instance_method_on_any_instance_of_a_class
+    should_stub_instance_method_on_any_instance_of_a_class
+  end
+  
+  def test_should_stub_instance_method_on_any_instance_of_a_class_again
+    should_stub_instance_method_on_any_instance_of_a_class
+  end
+  
+  def test_should_stub_two_different_class_methods
+    should_stub_two_different_class_methods
+  end
+  
+  def test_should_stub_two_different_class_methods_again
+    should_stub_two_different_class_methods
+  end
+  
+  private
+  
+  def should_stub_module_method
+    Thingy.expects(:wotsit).returns(:dooda)
+    assert_equal :dooda, Thingy.wotsit
+  end
+  
+  def should_stub_class_method
+    widgets = [Widget.new]
+    Widget.expects(:find).with(:all).returns(widgets)
+    assert_equal widgets, Widget.find(:all)
+  end 
+  
+  def should_stub_two_different_class_methods
+    found_widgets = [Widget.new]
+    created_widget = Widget.new
+    Widget.expects(:find).with(:all).returns(found_widgets)
+    Widget.expects(:create).with(:model => 'wombat').returns(created_widget)
+    assert_equal found_widgets, Widget.find(:all)
+    assert_equal created_widget, Widget.create(:model => 'wombat')
+  end
+  
+  def should_stub_instance_method_on_any_instance_of_a_class
+    Widget.any_instance.expects(:model).at_least_once.returns('another_model')
+    widget_1 = Widget.new
+    widget_2 = Widget.new
+    assert_equal 'another_model', widget_1.model
+    assert_equal 'another_model', widget_2.model
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/active_record_test_case.rb b/vendor/gems/mocha-0.5.6/test/active_record_test_case.rb
new file mode 100644
index 0000000..ae65073
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/active_record_test_case.rb
@@ -0,0 +1,36 @@
+module ActiveRecordTestCase
+
+  def setup_with_fixtures
+    methods_called << :setup_with_fixtures
+  end
+
+  alias_method :setup, :setup_with_fixtures
+
+  def teardown_with_fixtures
+    methods_called << :teardown_with_fixtures
+  end
+
+  alias_method :teardown, :teardown_with_fixtures
+
+  def self.method_added(method)
+    case method.to_s
+    when 'setup'
+      unless method_defined?(:setup_without_fixtures)
+        alias_method :setup_without_fixtures, :setup
+        define_method(:setup) do
+          setup_with_fixtures
+          setup_without_fixtures
+        end
+      end
+    when 'teardown'
+      unless method_defined?(:teardown_without_fixtures)
+        alias_method :teardown_without_fixtures, :teardown
+        define_method(:teardown) do
+          teardown_without_fixtures
+          teardown_with_fixtures
+        end
+      end
+    end
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/deprecation_disabler.rb b/vendor/gems/mocha-0.5.6/test/deprecation_disabler.rb
new file mode 100644
index 0000000..c57fb3c
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/deprecation_disabler.rb
@@ -0,0 +1,15 @@
+require 'mocha/deprecation'
+
+module DeprecationDisabler
+
+  def disable_deprecations
+    original_mode = Mocha::Deprecation.mode
+    Mocha::Deprecation.mode = :disabled
+    begin
+      yield
+    ensure
+      Mocha::Deprecation.mode = original_mode
+    end
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/execution_point.rb b/vendor/gems/mocha-0.5.6/test/execution_point.rb
new file mode 100644
index 0000000..33c8569
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/execution_point.rb
@@ -0,0 +1,34 @@
+class ExecutionPoint
+  
+  attr_reader :backtrace
+
+  def self.current
+    new(caller)
+  end
+  
+  def initialize(backtrace)
+    @backtrace = backtrace
+  end
+  
+  def file_name
+    /\A(.*?):\d+/.match(@backtrace.first)[1]
+  end
+  
+  def line_number
+    Integer(/\A.*?:(\d+)/.match(@backtrace.first)[1])
+  end
+
+  def ==(other)
+    return false unless other.is_a?(ExecutionPoint)
+    (file_name == other.file_name) and (line_number == other.line_number)
+  end
+  
+  def to_s
+    "file: #{file_name} line: #{line_number}"
+  end
+  
+  def inspect
+    to_s
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/integration/._mocha_test_result_integration_test.rb b/vendor/gems/mocha-0.5.6/test/integration/._mocha_test_result_integration_test.rb
new file mode 100644
index 0000000..78cbfbe
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/integration/._mocha_test_result_integration_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/integration/._stubba_integration_test.rb b/vendor/gems/mocha-0.5.6/test/integration/._stubba_integration_test.rb
new file mode 100644
index 0000000..c88497c
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/integration/._stubba_integration_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/integration/._stubba_test_result_integration_test.rb b/vendor/gems/mocha-0.5.6/test/integration/._stubba_test_result_integration_test.rb
new file mode 100644
index 0000000..931f631
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/integration/._stubba_test_result_integration_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/integration/mocha_test_result_integration_test.rb b/vendor/gems/mocha-0.5.6/test/integration/mocha_test_result_integration_test.rb
new file mode 100644
index 0000000..d5f29e8
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/integration/mocha_test_result_integration_test.rb
@@ -0,0 +1,105 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/standalone'
+require 'mocha/test_case_adapter'
+require 'execution_point'
+
+class MochaTestResultIntegrationTest < Test::Unit::TestCase
+  
+  def test_should_include_expectation_verification_in_assertion_count
+    test_result = run_test do
+      object = mock()
+      object.expects(:message)
+      object.message
+    end
+    assert_equal 1, test_result.assertion_count
+  end
+  
+  def test_should_include_assertions_in_assertion_count
+    test_result = run_test do
+      assert true
+    end
+    assert_equal 1, test_result.assertion_count
+  end
+  
+  def test_should_not_include_stubbing_expectation_verification_in_assertion_count
+    test_result = run_test do
+      object = mock()
+      object.stubs(:message)
+      object.message
+    end
+    assert_equal 0, test_result.assertion_count
+  end
+  
+  def test_should_include_expectation_verification_failure_in_failure_count
+    test_result = run_test do
+      object = mock()
+      object.expects(:message)
+    end
+    assert_equal 1, test_result.failure_count
+  end
+  
+  def test_should_include_unexpected_verification_failure_in_failure_count
+    test_result = run_test do
+      object = mock()
+      object.message
+    end
+    assert_equal 1, test_result.failure_count
+  end
+  
+  def test_should_include_assertion_failure_in_failure_count
+    test_result = run_test do
+      flunk
+    end
+    assert_equal 1, test_result.failure_count
+  end
+  
+  def test_should_display_backtrace_indicating_line_number_where_expects_was_called
+    test_result = Test::Unit::TestResult.new
+    faults = []
+    test_result.add_listener(Test::Unit::TestResult::FAULT, &lambda { |fault| faults << fault })
+    execution_point = nil
+    run_test(test_result) do
+      object = mock()
+      execution_point = ExecutionPoint.current; object.expects(:message)
+    end
+    assert_equal 1, faults.length
+    assert_equal execution_point, ExecutionPoint.new(faults.first.location)
+  end
+  
+  def test_should_display_backtrace_indicating_line_number_where_unexpected_method_was_called
+    test_result = Test::Unit::TestResult.new
+    faults = []
+    test_result.add_listener(Test::Unit::TestResult::FAULT, &lambda { |fault| faults << fault })
+    execution_point = nil
+    run_test(test_result) do
+      object = mock()
+      execution_point = ExecutionPoint.current; object.message 
+    end
+    assert_equal 1, faults.length
+    assert_equal execution_point, ExecutionPoint.new(faults.first.location)
+  end
+  
+  def test_should_display_backtrace_indicating_line_number_where_failing_assertion_was_called
+    test_result = Test::Unit::TestResult.new
+    faults = []
+    test_result.add_listener(Test::Unit::TestResult::FAULT, &lambda { |fault| faults << fault })
+    execution_point = nil
+    run_test(test_result) do
+      execution_point = ExecutionPoint.current; flunk
+    end
+    assert_equal 1, faults.length
+    assert_equal execution_point, ExecutionPoint.new(faults.first.location)
+  end
+  
+  def run_test(test_result = Test::Unit::TestResult.new, &block)
+    test_class = Class.new(Test::Unit::TestCase) do
+      include Mocha::Standalone
+      include Mocha::TestCaseAdapter
+      define_method(:test_me, &block)
+    end
+    test = test_class.new(:test_me)
+    test.run(test_result) {}
+    test_result
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/integration/stubba_integration_test.rb b/vendor/gems/mocha-0.5.6/test/integration/stubba_integration_test.rb
new file mode 100644
index 0000000..4285c17
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/integration/stubba_integration_test.rb
@@ -0,0 +1,89 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/object'
+require 'mocha/test_case_adapter'
+require 'mocha/standalone'
+
+class StubbaIntegrationTest < Test::Unit::TestCase
+  
+  class DontMessWithMe
+    def self.my_class_method
+      :original_return_value
+    end
+    def my_instance_method
+      :original_return_value
+    end
+  end
+  
+  def test_should_stub_class_method_within_test
+    test = build_test do
+      DontMessWithMe.expects(:my_class_method).returns(:new_return_value)
+      assert_equal :new_return_value, DontMessWithMe.my_class_method
+    end
+
+    test_result = Test::Unit::TestResult.new
+    test.run(test_result) {}
+    assert test_result.passed?
+  end
+
+  def test_should_leave_stubbed_class_method_unchanged_after_test
+    test = build_test do
+      DontMessWithMe.expects(:my_class_method).returns(:new_return_value)
+    end
+
+    test.run(Test::Unit::TestResult.new) {}
+    assert_equal :original_return_value, DontMessWithMe.my_class_method
+  end
+  
+  def test_should_reset_class_expectations_after_test
+    test = build_test do
+      DontMessWithMe.expects(:my_class_method)
+    end
+    
+    test.run(Test::Unit::TestResult.new) {}
+    assert_equal 0, DontMessWithMe.mocha.expectations.length
+  end  
+
+  def test_should_stub_instance_method_within_test
+    instance = DontMessWithMe.new
+    test = build_test do
+      instance.expects(:my_instance_method).returns(:new_return_value)
+      assert_equal :new_return_value, instance.my_instance_method
+    end
+    test_result = Test::Unit::TestResult.new
+    test.run(test_result) {}
+    assert test_result.passed?
+  end
+  
+  def test_should_leave_stubbed_instance_method_unchanged_after_test
+    instance = DontMessWithMe.new
+    test = build_test do
+      instance.expects(:my_instance_method).returns(:new_return_value)
+    end
+
+    test.run(Test::Unit::TestResult.new) {}
+    assert_equal :original_return_value, instance.my_instance_method
+  end
+  
+  def test_should_reset_instance_expectations_after_test
+    instance = DontMessWithMe.new
+    test = build_test do
+      instance.expects(:my_instance_method).returns(:new_return_value)
+    end
+    
+    test.run(Test::Unit::TestResult.new) {}
+    assert_equal 0, instance.mocha.expectations.length
+  end  
+
+  private
+
+  def build_test(&block)
+    test_class = Class.new(Test::Unit::TestCase) do
+      include Mocha::Standalone
+      include Mocha::TestCaseAdapter
+      define_method(:test_me, &block)
+    end
+    test_class.new(:test_me)
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/integration/stubba_test_result_integration_test.rb b/vendor/gems/mocha-0.5.6/test/integration/stubba_test_result_integration_test.rb
new file mode 100644
index 0000000..34264e7
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/integration/stubba_test_result_integration_test.rb
@@ -0,0 +1,85 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/object'
+require 'mocha/standalone'
+require 'mocha/test_case_adapter'
+require 'execution_point'
+
+class StubbaTestResultIntegrationTest < Test::Unit::TestCase
+
+  def test_should_include_expectation_verification_in_assertion_count
+    test_result = run_test do
+      object = Class.new { def message; end }.new
+      object.expects(:message)
+      object.message
+    end
+    assert_equal 1, test_result.assertion_count
+  end
+  
+  def test_should_include_assertions_in_assertion_count
+    test_result = run_test do
+      assert true
+    end
+    assert_equal 1, test_result.assertion_count
+  end
+  
+  def test_should_not_include_stubbing_expectation_verification_in_assertion_count
+    test_result = run_test do
+      object = Class.new { def message; end }.new
+      object.stubs(:message)
+      object.message
+    end
+    assert_equal 0, test_result.assertion_count
+  end
+  
+  def test_should_include_expectation_verification_failure_in_failure_count
+    test_result = run_test do
+      object = Class.new { def message; end }.new
+      object.expects(:message)
+    end
+    assert_equal 1, test_result.failure_count
+  end
+  
+  def test_should_include_assertion_failure_in_failure_count
+    test_result = run_test do
+      flunk
+    end
+    assert_equal 1, test_result.failure_count
+  end
+  
+  def test_should_display_backtrace_indicating_line_number_where_expects_was_called
+    test_result = Test::Unit::TestResult.new
+    faults = []
+    test_result.add_listener(Test::Unit::TestResult::FAULT, &lambda { |fault| faults << fault })
+    execution_point = nil
+    run_test(test_result) do
+      object = Class.new { def message; end }.new
+      execution_point = ExecutionPoint.current; object.expects(:message)
+    end
+    assert_equal 1, faults.length
+    assert_equal execution_point, ExecutionPoint.new(faults.first.location)
+  end
+  
+  def test_should_display_backtrace_indicating_line_number_where_failing_assertion_was_called
+    test_result = Test::Unit::TestResult.new
+    faults = []
+    test_result.add_listener(Test::Unit::TestResult::FAULT, &lambda { |fault| faults << fault })
+    execution_point = nil
+    run_test(test_result) do
+      execution_point = ExecutionPoint.current; flunk
+    end
+    assert_equal 1, faults.length
+    assert_equal execution_point, ExecutionPoint.new(faults.first.location)
+  end
+  
+  def run_test(test_result = Test::Unit::TestResult.new, &block)
+    test_class = Class.new(Test::Unit::TestCase) do
+      include Mocha::Standalone
+      include Mocha::TestCaseAdapter
+      define_method(:test_me, &block)
+    end
+    test = test_class.new(:test_me)
+    test.run(test_result) {}
+    test_result
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/method_definer.rb b/vendor/gems/mocha-0.5.6/test/method_definer.rb
new file mode 100644
index 0000000..1aef886
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/method_definer.rb
@@ -0,0 +1,18 @@
+require 'mocha/metaclass'
+
+class Object
+  
+  def define_instance_method(method_symbol, &block)
+    __metaclass__.send(:define_method, method_symbol, block)
+  end
+
+  def replace_instance_method(method_symbol, &block)
+    raise "Cannot replace #{method_symbol} as #{self} does not respond to it." unless self.respond_to?(method_symbol)
+    define_instance_method(method_symbol, &block)
+  end
+
+  def define_instance_accessor(*symbols)
+    symbols.each { |symbol| __metaclass__.send(:attr_accessor, symbol) }
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/test_helper.rb b/vendor/gems/mocha-0.5.6/test/test_helper.rb
new file mode 100644
index 0000000..dc04942
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/test_helper.rb
@@ -0,0 +1,12 @@
+unless defined?(STANDARD_OBJECT_PUBLIC_INSTANCE_METHODS)
+  STANDARD_OBJECT_PUBLIC_INSTANCE_METHODS = Object.public_instance_methods
+end
+
+$:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
+$:.unshift File.expand_path(File.join(File.dirname(__FILE__)))
+$:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'unit'))
+$:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'unit', 'parameter_matchers'))
+$:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'integration'))
+$:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'acceptance'))
+
+require 'test/unit'
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/test_runner.rb b/vendor/gems/mocha-0.5.6/test/test_runner.rb
new file mode 100644
index 0000000..fbadd92
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/test_runner.rb
@@ -0,0 +1,31 @@
+require 'test/unit/testresult'
+require 'test/unit/testcase'
+require 'mocha/standalone'
+require 'mocha/test_case_adapter'
+
+module TestRunner
+  
+  def run_test(test_result = Test::Unit::TestResult.new, &block)
+    test_class = Class.new(Test::Unit::TestCase) do
+      include Mocha::Standalone
+      include Mocha::TestCaseAdapter
+      define_method(:test_me, &block)
+    end
+    test = test_class.new(:test_me)
+    test.run(test_result) {}
+    class << test_result
+      attr_reader :failures, :errors
+    end
+    test_result
+  end
+  
+  def assert_passed(test_result)
+    flunk "Test failed unexpectedly with message: #{test_result.failures}" if test_result.failure_count > 0
+    flunk "Test failed unexpectedly with message: #{test_result.errors}" if test_result.error_count > 0
+  end
+
+  def assert_failed(test_result)
+    flunk "Test passed unexpectedly" if test_result.passed?
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._any_instance_method_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._any_instance_method_test.rb
new file mode 100644
index 0000000..83d91fd
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._any_instance_method_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._auto_verify_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._auto_verify_test.rb
new file mode 100644
index 0000000..9052afc
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._auto_verify_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._central_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._central_test.rb
new file mode 100644
index 0000000..a8cc77d
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._central_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._class_method_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._class_method_test.rb
new file mode 100644
index 0000000..30c6ce8
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._class_method_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._expectation_error_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._expectation_error_test.rb
new file mode 100644
index 0000000..6bd7f71
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._expectation_error_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._expectation_list_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._expectation_list_test.rb
new file mode 100644
index 0000000..753636a
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._expectation_list_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._expectation_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._expectation_test.rb
new file mode 100644
index 0000000..b92a766
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._expectation_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._hash_inspect_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._hash_inspect_test.rb
new file mode 100644
index 0000000..2d092d9
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._hash_inspect_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._method_matcher_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._method_matcher_test.rb
new file mode 100644
index 0000000..5de8376
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._method_matcher_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._missing_expectation_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._missing_expectation_test.rb
new file mode 100644
index 0000000..166d782
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._missing_expectation_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._mock_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._mock_test.rb
new file mode 100644
index 0000000..e9005d1
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._mock_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._object_inspect_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._object_inspect_test.rb
new file mode 100644
index 0000000..e39ba31
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._object_inspect_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._parameters_matcher_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._parameters_matcher_test.rb
new file mode 100644
index 0000000..ca04d98
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._parameters_matcher_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/._sequence_test.rb b/vendor/gems/mocha-0.5.6/test/unit/._sequence_test.rb
new file mode 100644
index 0000000..ec9e9d7
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/._sequence_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/any_instance_method_test.rb b/vendor/gems/mocha-0.5.6/test/unit/any_instance_method_test.rb
new file mode 100644
index 0000000..804fcde
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/any_instance_method_test.rb
@@ -0,0 +1,126 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'method_definer'
+require 'mocha/mock'
+require 'mocha/any_instance_method'
+
+class AnyInstanceMethodTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_hide_original_method
+    klass = Class.new { def method_x; end }
+    method = AnyInstanceMethod.new(klass, :method_x)
+    hidden_method_x = method.hidden_method.to_sym
+    
+    method.hide_original_method
+    
+    assert klass.method_defined?(hidden_method_x)
+  end
+  
+  def test_should_not_hide_original_method_if_it_is_not_defined
+    klass = Class.new
+    method = AnyInstanceMethod.new(klass, :method_x)
+    hidden_method_x = method.hidden_method.to_sym
+    
+    method.hide_original_method
+    
+    assert_equal false, klass.method_defined?(hidden_method_x)
+  end
+  
+  def test_should_define_a_new_method
+    klass = Class.new { def method_x; end } 
+    method = AnyInstanceMethod.new(klass, :method_x)
+    mocha = Mock.new
+    mocha.expects(:method_x).with(:param1, :param2).returns(:result)
+    any_instance = Object.new
+    any_instance.define_instance_method(:mocha) { mocha }
+    klass.define_instance_method(:any_instance) { any_instance }
+    
+    method.hide_original_method
+    method.define_new_method
+
+    instance = klass.new
+    result = instance.method_x(:param1, :param2)
+        
+    assert_equal :result, result
+    mocha.verify
+  end
+
+  def test_should_restore_original_method
+    klass = Class.new { def method_x; end }
+    method = AnyInstanceMethod.new(klass, :method_x)
+    hidden_method_x = method.hidden_method.to_sym
+    klass.send(:define_method, hidden_method_x, Proc.new { :original_result }) 
+    
+    method.remove_new_method
+    method.restore_original_method
+    
+    instance = klass.new
+    assert_equal :original_result, instance.method_x 
+    assert !klass.method_defined?(hidden_method_x)
+  end
+
+  def test_should_not_restore_original_method_if_hidden_method_not_defined
+    klass = Class.new { def method_x; :new_result; end }
+    method = AnyInstanceMethod.new(klass, :method_x)
+    
+    method.restore_original_method
+    
+    instance = klass.new
+    assert_equal :new_result, instance.method_x 
+  end
+
+  def test_should_call_remove_new_method
+    klass = Class.new { def method_x; end }
+    any_instance = Mock.new
+    any_instance.stubs(:reset_mocha)
+    klass.define_instance_method(:any_instance) { any_instance }
+    method = AnyInstanceMethod.new(klass, :method_x)
+    method.replace_instance_method(:restore_original_method) { }
+    method.define_instance_accessor(:remove_called)
+    method.replace_instance_method(:remove_new_method) { self.remove_called = true }
+    
+    method.unstub
+    
+    assert method.remove_called
+  end
+
+  def test_should_call_restore_original_method
+    klass = Class.new { def method_x; end }
+    any_instance = Mock.new
+    any_instance.stubs(:reset_mocha)
+    klass.define_instance_method(:any_instance) { any_instance }
+    method = AnyInstanceMethod.new(klass, :method_x)
+    method.replace_instance_method(:remove_new_method) { }
+    method.define_instance_accessor(:restore_called)
+    method.replace_instance_method(:restore_original_method) { self.restore_called = true }
+    
+    method.unstub
+    
+    assert method.restore_called
+  end
+
+  def test_should_call_reset_mocha
+    klass = Class.new { def method_x; end }
+    any_instance = Class.new { attr_accessor :mocha_was_reset; def reset_mocha; self.mocha_was_reset = true; end }.new
+    klass.define_instance_method(:any_instance) { any_instance }
+    method = AnyInstanceMethod.new(klass, :method_x)
+    method.replace_instance_method(:remove_new_method) { }
+    method.replace_instance_method(:restore_original_method) { }
+    
+    method.unstub
+
+    assert any_instance.mocha_was_reset
+  end
+
+  def test_should_return_any_instance_mocha_for_stubbee
+    mocha = Object.new
+    any_instance = Object.new
+    any_instance.define_instance_method(:mocha) { mocha }
+    stubbee = Class.new
+    stubbee.define_instance_method(:any_instance) { any_instance }
+    method = AnyInstanceMethod.new(stubbee, :method_name)
+    assert_equal stubbee.any_instance.mocha, method.mock
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/array_inspect_test.rb b/vendor/gems/mocha-0.5.6/test/unit/array_inspect_test.rb
new file mode 100644
index 0000000..9cc06a4
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/array_inspect_test.rb
@@ -0,0 +1,16 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/inspect'
+
+class ArrayInstanceTest < Test::Unit::TestCase
+  
+  def test_should_use_inspect
+    array = [1, 2]
+    assert_equal array.inspect, array.mocha_inspect
+  end
+  
+  def test_should_use_mocha_inspect_on_each_item
+    array = [1, 2, "chris"]
+    assert_equal "[1, 2, 'chris']", array.mocha_inspect
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/auto_verify_test.rb b/vendor/gems/mocha-0.5.6/test/unit/auto_verify_test.rb
new file mode 100644
index 0000000..10a6124
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/auto_verify_test.rb
@@ -0,0 +1,129 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/auto_verify'
+require 'method_definer'
+
+class AutoVerifyTest < Test::Unit::TestCase
+  
+  attr_reader :test_case
+  
+  def setup
+    @test_case = Object.new
+    class << test_case
+      include Mocha::AutoVerify
+    end
+  end
+  
+  def test_should_build_mock
+    mock = test_case.mock
+    assert mock.is_a?(Mocha::Mock)
+  end
+  
+  def test_should_add_expectations_to_mock
+    mock = test_case.mock(:method_1 => 'result_1', :method_2 => 'result_2')
+    assert_equal 'result_1', mock.method_1
+    assert_equal 'result_2', mock.method_2
+  end
+  
+  def test_should_build_stub
+    stub = test_case.stub
+    assert stub.is_a?(Mocha::Mock)
+  end
+  
+  def test_should_add_expectation_to_stub
+    stub = test_case.stub(:method_1 => 'result_1', :method_2 => 'result_2')
+    assert_equal 'result_1', stub.method_1
+    assert_equal 'result_2', stub.method_2
+  end
+  
+  def test_should_build_stub_that_stubs_all_methods
+    stub = test_case.stub_everything
+    assert stub.everything_stubbed
+  end
+  
+  def test_should_add_expectations_to_stub_that_stubs_all_methods
+    stub = test_case.stub_everything(:method_1 => 'result_1', :method_2 => 'result_2')
+    assert_equal 'result_1', stub.method_1
+    assert_equal 'result_2', stub.method_2
+  end
+  
+  def test_should_always_new_mock
+    assert_not_equal test_case.mock, test_case.mock
+  end
+  
+  def test_should_always_build_new_stub
+    assert_not_equal test_case.stub, test_case.stub
+  end
+  
+  def test_should_always_build_new_stub_that_stubs_all_methods
+    assert_not_equal test_case.stub, test_case.stub
+  end
+  
+  def test_should_store_each_new_mock
+    expected = Array.new(3) { test_case.mock }
+    assert_equal expected, test_case.mocks
+  end
+  
+  def test_should_store_each_new_stub
+    expected = Array.new(3) { test_case.stub }
+    assert_equal expected, test_case.mocks
+  end
+  
+  def test_should_store_each_new_stub_that_stubs_all_methods
+    expected = Array.new(3) { test_case.stub_everything }
+    assert_equal expected, test_case.mocks
+  end
+  
+  def test_should_verify_each_mock
+    mocks = Array.new(3) do
+      mock = Object.new
+      mock.define_instance_accessor(:verify_called)
+      class << mock
+        def verify(&block)
+          self.verify_called = true
+        end
+      end
+      mock
+    end
+    test_case.replace_instance_method(:mocks)  { mocks }
+    test_case.verify_mocks
+    assert mocks.all? { |mock| mock.verify_called }
+  end
+  
+  def test_should_yield_to_block_for_each_assertion
+    mock_class = Class.new do
+      def verify(&block); yield; end
+    end
+    mock = mock_class.new
+    test_case.replace_instance_method(:mocks)  { [mock] }
+    yielded = false
+    test_case.verify_mocks { yielded = true }
+    assert yielded
+  end
+  
+  def test_should_reset_mocks_on_teardown
+    mock = Class.new { define_method(:verify) {} }.new
+    test_case.mocks << mock
+    test_case.teardown_mocks
+    assert test_case.mocks.empty?
+  end
+  
+  def test_should_create_named_mock
+    mock = test_case.mock('named_mock')
+    assert_equal '#<Mock:named_mock>', mock.mocha_inspect
+  end
+  
+  def test_should_create_named_stub
+    stub = test_case.stub('named_stub')
+    assert_equal '#<Mock:named_stub>', stub.mocha_inspect
+  end
+  
+  def test_should_create_named_stub_that_stubs_all_methods
+    stub = test_case.stub_everything('named_stub')
+    assert_equal '#<Mock:named_stub>', stub.mocha_inspect
+  end
+  
+  def test_should_build_sequence
+    assert_not_nil test_case.sequence('name')
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/central_test.rb b/vendor/gems/mocha-0.5.6/test/unit/central_test.rb
new file mode 100644
index 0000000..2cc8345
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/central_test.rb
@@ -0,0 +1,124 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/central'
+require 'mocha/mock'
+require 'method_definer'
+
+class CentralTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_start_with_empty_stubba_methods
+    stubba = Central.new
+    
+    assert_equal [], stubba.stubba_methods
+  end
+  
+  def test_should_stub_method_if_not_already_stubbed
+    method = Mock.new
+    method.expects(:stub)
+    stubba = Central.new
+    
+    stubba.stub(method)
+    
+    method.verify
+  end
+  
+  def test_should_not_stub_method_if_already_stubbed
+    method = Mock.new
+    method.expects(:stub).times(0)
+    stubba = Central.new
+    stubba_methods = Mock.new
+    stubba_methods.stubs(:include?).with(method).returns(true)
+    stubba.stubba_methods = stubba_methods
+    
+    stubba.stub(method)
+    
+    method.verify
+  end
+  
+  def test_should_record_method
+    method = Mock.new
+    method.expects(:stub)
+    stubba = Central.new
+    
+    stubba.stub(method)
+    
+    assert_equal [method], stubba.stubba_methods
+  end
+  
+  def test_should_unstub_all_methods
+    stubba = Central.new
+    method_1 = Mock.new
+    method_1.expects(:unstub)
+    method_2 = Mock.new
+    method_2.expects(:unstub)
+    stubba.stubba_methods = [method_1, method_2]
+
+    stubba.unstub_all
+    
+    assert_equal [], stubba.stubba_methods
+    method_1.verify
+    method_2.verify
+  end
+  
+  def test_should_collect_mocks_from_all_methods
+    method_1 = Mock.new
+    method_1.stubs(:mock).returns(:mock_1)
+
+    method_2 = Mock.new
+    method_2.stubs(:mock).returns(:mock_2)
+
+    stubba = Central.new
+    stubba.stubba_methods = [method_1, method_2]
+    
+    assert_equal 2, stubba.unique_mocks.length
+    assert stubba.unique_mocks.include?(:mock_1)
+    assert stubba.unique_mocks.include?(:mock_2)
+  end
+
+  def test_should_return_unique_mochas
+    method_1 = Mock.new
+    method_1.stubs(:mock).returns(:mock_1)
+
+    method_2 = Mock.new
+    method_2.stubs(:mock).returns(:mock_1)
+
+    stubba = Central.new
+    stubba.stubba_methods = [method_1, method_2]
+    
+    assert_equal [:mock_1], stubba.unique_mocks
+  end
+  
+  def test_should_call_verify_on_all_unique_mocks
+    mock_class = Class.new do
+      attr_accessor :verify_called
+      def verify
+        self.verify_called = true
+      end
+    end
+    mocks = [mock_class.new, mock_class.new]
+    stubba = Central.new
+    stubba.replace_instance_method(:unique_mocks) { mocks }
+    
+    stubba.verify_all
+    
+    assert mocks.all? { |mock| mock.verify_called }
+  end
+
+  def test_should_call_verify_on_all_unique_mochas
+    mock_class = Class.new do
+      def verify(&block)
+        yield if block_given?
+      end
+    end
+    stubba = Central.new
+    stubba.replace_instance_method(:unique_mocks) { [mock_class.new] }
+    yielded = false
+    
+    stubba.verify_all { yielded = true }
+    
+    assert yielded
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/class_method_test.rb b/vendor/gems/mocha-0.5.6/test/unit/class_method_test.rb
new file mode 100644
index 0000000..95d0599
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/class_method_test.rb
@@ -0,0 +1,200 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'method_definer'
+require 'mocha/mock'
+
+require 'mocha/class_method'
+
+class ClassMethodTest < Test::Unit::TestCase
+  
+  include Mocha
+
+  def test_should_provide_hidden_version_of_method_name_starting_with_prefix
+    method = ClassMethod.new(nil, :original_method_name)
+    assert_match(/^__stubba__/, method.hidden_method)
+  end
+  
+  def test_should_provide_hidden_version_of_method_name_ending_with_suffix
+    method = ClassMethod.new(nil, :original_method_name)
+    assert_match(/__stubba__$/, method.hidden_method)
+  end
+  
+  def test_should_provide_hidden_version_of_method_name_including_original_method_name
+    method = ClassMethod.new(nil, :original_method_name)
+    assert_match(/original_method_name/, method.hidden_method)
+  end
+  
+  def test_should_provide_hidden_version_of_method_name_substituting_question_mark
+    method = ClassMethod.new(nil, :question_mark?)
+    assert_no_match(/\?/, method.hidden_method)
+    assert_match(/question_mark_substituted_character_63/, method.hidden_method)
+  end
+  
+  def test_should_provide_hidden_version_of_method_name_substituting_exclamation_mark
+    method = ClassMethod.new(nil, :exclamation_mark!)
+    assert_no_match(/!/, method.hidden_method)
+    assert_match(/exclamation_mark_substituted_character_33/, method.hidden_method)
+  end
+
+  def test_should_provide_hidden_version_of_method_name_substituting_equals_sign
+    method = ClassMethod.new(nil, :equals_sign=)
+    assert_no_match(/\=/, method.hidden_method)
+    assert_match(/equals_sign_substituted_character_61/, method.hidden_method)
+  end
+
+  def test_should_provide_hidden_version_of_method_name_substituting_brackets
+    method = ClassMethod.new(nil, :[])
+    assert_no_match(/\[\]/, method.hidden_method)
+    assert_match(/substituted_character_91__substituted_character_93/, method.hidden_method)
+  end
+  
+  def test_should_provide_hidden_version_of_method_name_substituting_plus_sign
+    method = ClassMethod.new(nil, :+)
+    assert_no_match(/\+/, method.hidden_method)
+    assert_match(/substituted_character_43/, method.hidden_method)
+  end
+  
+  def test_should_hide_original_method
+    klass = Class.new { def self.method_x; end }
+    method = ClassMethod.new(klass, :method_x)
+    hidden_method_x = method.hidden_method
+    
+    method.hide_original_method
+
+    assert klass.respond_to?(hidden_method_x)
+  end
+  
+  def test_should_respond_to_original_method_name_after_original_method_has_been_hidden
+    klass = Class.new { def self.original_method_name; end }
+    method = ClassMethod.new(klass, :original_method_name)
+    hidden_method_x = method.hidden_method
+    
+    method.hide_original_method
+
+    assert klass.respond_to?(:original_method_name)
+  end
+  
+  def test_should_not_hide_original_method_if_method_not_defined
+    klass = Class.new
+    method = ClassMethod.new(klass, :method_x)
+    hidden_method_x = method.hidden_method
+    
+    method.hide_original_method
+
+    assert_equal false, klass.respond_to?(hidden_method_x)
+  end
+  
+  def test_should_define_a_new_method_which_should_call_mocha_method_missing
+    klass = Class.new { def self.method_x; end }
+    mocha = Mocha::Mock.new
+    klass.define_instance_method(:mocha) { mocha }
+    mocha.expects(:method_x).with(:param1, :param2).returns(:result)
+    method = ClassMethod.new(klass, :method_x)
+    
+    method.hide_original_method
+    method.define_new_method
+    result = klass.method_x(:param1, :param2)
+    
+    assert_equal :result, result
+    mocha.verify
+  end
+  
+  def test_should_remove_new_method
+    klass = Class.new { def self.method_x; end }
+    method = ClassMethod.new(klass, :method_x)
+    
+    method.remove_new_method
+    
+    assert_equal false, klass.respond_to?(:method_x)
+  end
+
+  def test_should_restore_original_method
+    klass = Class.new { def self.method_x; end }
+    method = ClassMethod.new(klass, :method_x)
+    hidden_method_x = method.hidden_method.to_sym
+    klass.define_instance_method(hidden_method_x) { :original_result }
+
+    method.remove_new_method
+    method.restore_original_method
+    
+    assert_equal :original_result, klass.method_x 
+    assert_equal false, klass.respond_to?(hidden_method_x)
+  end
+
+  def test_should_not_restore_original_method_if_hidden_method_is_not_defined
+    klass = Class.new { def self.method_x; :new_result; end }
+    method = ClassMethod.new(klass, :method_x)
+
+    method.restore_original_method
+    
+    assert_equal :new_result, klass.method_x
+  end
+
+  def test_should_call_hide_original_method
+    klass = Class.new { def self.method_x; end }
+    method = ClassMethod.new(klass, :method_x)
+    method.hide_original_method
+    method.define_instance_accessor(:hide_called)
+    method.replace_instance_method(:hide_original_method) { self.hide_called = true }
+    
+    method.stub
+    
+    assert method.hide_called
+  end
+
+  def test_should_call_define_new_method
+    klass = Class.new { def self.method_x; end }
+    method = ClassMethod.new(klass, :method_x)
+    method.define_instance_accessor(:define_called)
+    method.replace_instance_method(:define_new_method) { self.define_called = true }
+    
+    method.stub
+    
+    assert method.define_called
+  end
+  
+  def test_should_call_remove_new_method
+    klass = Class.new { def self.method_x; end }
+    klass.define_instance_method(:reset_mocha) { }
+    method = ClassMethod.new(klass, :method_x)
+    method.define_instance_accessor(:remove_called)
+    method.replace_instance_method(:remove_new_method) { self.remove_called = true }
+    
+    method.unstub
+    
+    assert method.remove_called
+  end
+
+  def test_should_call_restore_original_method
+    klass = Class.new { def self.method_x; end }
+    klass.define_instance_method(:reset_mocha) { }
+    method = ClassMethod.new(klass, :method_x)
+    method.define_instance_accessor(:restore_called)
+    method.replace_instance_method(:restore_original_method) { self.restore_called = true }
+    
+    method.unstub
+    
+    assert method.restore_called
+  end
+
+  def test_should_call_reset_mocha
+    klass = Class.new { def self.method_x; end }
+    klass.define_instance_accessor(:reset_called)
+    klass.define_instance_method(:reset_mocha) { self.reset_called = true }
+    method = ClassMethod.new(klass, :method_x)
+    method.replace_instance_method(:restore_original_method) { }
+    
+    method.unstub
+    
+    assert klass.reset_called
+  end
+  
+  def test_should_return_mock_for_stubbee
+    mocha = Object.new
+    stubbee = Object.new
+    stubbee.define_instance_accessor(:mocha) { mocha }
+    stubbee.mocha = nil
+    method = ClassMethod.new(stubbee, :method_name)
+    assert_equal stubbee.mocha, method.mock
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/date_time_inspect_test.rb b/vendor/gems/mocha-0.5.6/test/unit/date_time_inspect_test.rb
new file mode 100644
index 0000000..8a9b2ee
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/date_time_inspect_test.rb
@@ -0,0 +1,21 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/inspect'
+
+class TimeDateInspectTest < Test::Unit::TestCase
+  
+  def test_should_use_include_date_in_seconds
+    time = Time.now
+    assert_equal "#{time.inspect} (#{time.to_f} secs)", time.mocha_inspect
+  end
+  
+  def test_should_use_to_s_for_date
+    date = Date.new(2006, 1, 1)
+    assert_equal date.to_s, date.mocha_inspect
+  end
+  
+  def test_should_use_to_s_for_datetime
+    datetime = DateTime.new(2006, 1, 1)
+    assert_equal datetime.to_s, datetime.mocha_inspect
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/expectation_error_test.rb b/vendor/gems/mocha-0.5.6/test/unit/expectation_error_test.rb
new file mode 100644
index 0000000..6206acf
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/expectation_error_test.rb
@@ -0,0 +1,24 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/expectation_error'
+
+class ExpectationErrorTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_exclude_mocha_locations_from_backtrace
+    mocha_lib = "/username/workspace/mocha_wibble/lib/"
+    backtrace = [ mocha_lib + 'exclude/me/1', mocha_lib + 'exclude/me/2', '/keep/me', mocha_lib + 'exclude/me/3']
+    expectation_error = ExpectationError.new(nil, backtrace, mocha_lib)
+    assert_equal ['/keep/me'], expectation_error.backtrace
+  end
+
+  def test_should_determine_path_for_mocha_lib_directory
+    assert_match Regexp.new("/lib/$"), ExpectationError::LIB_DIRECTORY
+  end
+  
+  def test_should_set_error_message
+    expectation_error = ExpectationError.new('message')
+    assert_equal 'message', expectation_error.message
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/expectation_list_test.rb b/vendor/gems/mocha-0.5.6/test/unit/expectation_list_test.rb
new file mode 100644
index 0000000..59dd410
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/expectation_list_test.rb
@@ -0,0 +1,75 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/expectation_list'
+require 'mocha/expectation'
+require 'set'
+require 'method_definer'
+
+class ExpectationListTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_return_added_expectation
+    expectation_list = ExpectationList.new
+    expectation = Expectation.new(nil, :my_method)
+    assert_same expectation, expectation_list.add(expectation)
+  end
+
+  def test_should_find_matching_expectation
+    expectation_list = ExpectationList.new
+    expectation1 = Expectation.new(nil, :my_method).with(:argument1, :argument2)
+    expectation2 = Expectation.new(nil, :my_method).with(:argument3, :argument4)
+    expectation_list.add(expectation1)
+    expectation_list.add(expectation2)
+    assert_same expectation2, expectation_list.detect(:my_method, :argument3, :argument4)
+  end
+
+  def test_should_find_most_recent_matching_expectation
+    expectation_list = ExpectationList.new
+    expectation1 = Expectation.new(nil, :my_method).with(:argument1, :argument2)
+    expectation2 = Expectation.new(nil, :my_method).with(:argument1, :argument2)
+    expectation_list.add(expectation1)
+    expectation_list.add(expectation2)
+    assert_same expectation2, expectation_list.detect(:my_method, :argument1, :argument2)
+  end
+
+  def test_should_find_most_recent_matching_expectation_but_give_preference_to_those_allowing_invocations
+    expectation_list = ExpectationList.new
+    expectation1 = Expectation.new(nil, :my_method)
+    expectation2 = Expectation.new(nil, :my_method)
+    expectation1.define_instance_method(:invocations_allowed?) { true }
+    expectation2.define_instance_method(:invocations_allowed?) { false }
+    expectation_list.add(expectation1)
+    expectation_list.add(expectation2)
+    assert_same expectation1, expectation_list.detect(:my_method)
+  end
+
+  def test_should_find_most_recent_matching_expectation_if_no_matching_expectations_allow_invocations
+    expectation_list = ExpectationList.new
+    expectation1 = Expectation.new(nil, :my_method)
+    expectation2 = Expectation.new(nil, :my_method)
+    expectation1.define_instance_method(:invocations_allowed?) { false }
+    expectation2.define_instance_method(:invocations_allowed?) { false }
+    expectation_list.add(expectation1)
+    expectation_list.add(expectation2)
+    assert_same expectation2, expectation_list.detect(:my_method)
+  end
+
+  def test_should_find_expectations_for_the_same_method_no_matter_what_the_arguments
+    expectation_list = ExpectationList.new
+    expectation1 = Expectation.new(nil, :my_method).with(:argument1, :argument2)
+    expectation_list.add(expectation1)
+    expectation2 = Expectation.new(nil, :my_method).with(:argument3, :argument4)
+    expectation_list.add(expectation2)
+    assert_equal [expectation1, expectation2].to_set, expectation_list.similar(:my_method).to_set
+  end
+  
+  def test_should_ignore_expectations_for_different_methods
+    expectation_list = ExpectationList.new
+    expectation1 = Expectation.new(nil, :method1).with(:argument1, :argument2)
+    expectation_list.add(expectation1)
+    expectation2 = Expectation.new(nil, :method2).with(:argument1, :argument2)
+    expectation_list.add(expectation2)
+    assert_equal [expectation2], expectation_list.similar(:method2)
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/expectation_raiser_test.rb b/vendor/gems/mocha-0.5.6/test/unit/expectation_raiser_test.rb
new file mode 100644
index 0000000..3b46d8f
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/expectation_raiser_test.rb
@@ -0,0 +1,28 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/exception_raiser'
+
+class ExceptionRaiserTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_raise_exception_with_specified_class_and_default_message
+    exception_class = Class.new(StandardError)
+    raiser = ExceptionRaiser.new(exception_class, nil)
+    exception = assert_raises(exception_class) { raiser.evaluate }
+    assert_equal exception_class.to_s, exception.message
+  end
+
+  def test_should_raise_exception_with_specified_class_and_message
+    exception_class = Class.new(StandardError)
+    raiser = ExceptionRaiser.new(exception_class, 'message')
+    exception = assert_raises(exception_class) { raiser.evaluate }
+    assert_equal 'message', exception.message
+  end
+  
+  def test_should_raise_interrupt_exception_with_default_message_so_it_works_in_ruby_1_8_6
+    raiser = ExceptionRaiser.new(Interrupt, nil)
+    assert_raises(Interrupt) { raiser.evaluate }
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/expectation_test.rb b/vendor/gems/mocha-0.5.6/test/unit/expectation_test.rb
new file mode 100644
index 0000000..cdb38eb
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/expectation_test.rb
@@ -0,0 +1,483 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'method_definer'
+require 'mocha/expectation'
+require 'mocha/sequence'
+require 'execution_point'
+require 'deprecation_disabler'
+
+class ExpectationTest < Test::Unit::TestCase
+  
+  include Mocha
+  include DeprecationDisabler
+  
+  def new_expectation
+    Expectation.new(nil, :expected_method)
+  end
+  
+  def test_should_match_calls_to_same_method_with_any_parameters
+    assert new_expectation.match?(:expected_method, 1, 2, 3)
+  end
+  
+  def test_should_match_calls_to_same_method_with_exactly_zero_parameters
+    expectation = new_expectation.with()
+    assert expectation.match?(:expected_method)
+  end
+  
+  def test_should_not_match_calls_to_same_method_with_more_than_zero_parameters
+    expectation = new_expectation.with()
+    assert !expectation.match?(:expected_method, 1, 2, 3)
+  end
+  
+  def test_should_match_calls_to_same_method_with_expected_parameter_values
+    expectation = new_expectation.with(1, 2, 3)
+    assert expectation.match?(:expected_method, 1, 2, 3)
+  end
+  
+  def test_should_match_calls_to_same_method_with_parameters_constrained_as_expected
+    expectation = new_expectation.with() {|x, y, z| x + y == z}
+    assert expectation.match?(:expected_method, 1, 2, 3)
+  end
+  
+  def test_should_not_match_calls_to_different_method_with_parameters_constrained_as_expected
+    expectation = new_expectation.with() {|x, y, z| x + y == z}
+    assert !expectation.match?(:different_method, 1, 2, 3)
+  end
+  
+  def test_should_not_match_calls_to_different_methods_with_no_parameters
+    assert !new_expectation.match?(:unexpected_method)
+  end
+  
+  def test_should_not_match_calls_to_same_method_with_too_few_parameters
+    expectation = new_expectation.with(1, 2, 3)
+    assert !expectation.match?(:unexpected_method, 1, 2)
+  end
+  
+  def test_should_not_match_calls_to_same_method_with_too_many_parameters
+    expectation = new_expectation.with(1, 2)
+    assert !expectation.match?(:unexpected_method, 1, 2, 3)
+  end
+  
+  def test_should_not_match_calls_to_same_method_with_unexpected_parameter_values
+    expectation = new_expectation.with(1, 2, 3)
+    assert !expectation.match?(:unexpected_method, 1, 0, 3)
+  end
+  
+  def test_should_not_match_calls_to_same_method_with_parameters_not_constrained_as_expected
+    expectation = new_expectation.with() {|x, y, z| x + y == z}
+    assert !expectation.match?(:expected_method, 1, 0, 3)
+  end
+  
+  def test_should_allow_invocations_until_expected_invocation_count_is_one_and_actual_invocation_count_would_be_two
+    expectation = new_expectation.times(1)
+    assert expectation.invocations_allowed?
+    expectation.invoke
+    assert !expectation.invocations_allowed?
+  end
+  
+  def test_should_allow_invocations_until_expected_invocation_count_is_two_and_actual_invocation_count_would_be_three
+    expectation = new_expectation.times(2)
+    assert expectation.invocations_allowed?
+    expectation.invoke
+    assert expectation.invocations_allowed?
+    expectation.invoke
+    assert !expectation.invocations_allowed?
+  end
+
+  def test_should_allow_invocations_until_expected_invocation_count_is_a_range_from_two_to_three_and_actual_invocation_count_would_be_four
+    expectation = new_expectation.times(2..3)
+    assert expectation.invocations_allowed?
+    expectation.invoke
+    assert expectation.invocations_allowed?
+    expectation.invoke
+    assert expectation.invocations_allowed?
+    expectation.invoke
+    assert !expectation.invocations_allowed?
+  end
+  
+  def test_should_store_provided_backtrace
+    backtrace = Object.new
+    expectation = Expectation.new(nil, :expected_method, backtrace)
+    assert_equal backtrace, expectation.backtrace
+  end
+  
+  def test_should_default_backtrace_to_caller
+    execution_point = ExecutionPoint.current; expectation = Expectation.new(nil, :expected_method)
+    assert_equal execution_point, ExecutionPoint.new(expectation.backtrace)
+  end
+  
+  def test_should_not_yield
+    yielded = false
+    new_expectation.invoke() { yielded = true }
+    assert_equal false, yielded
+  end
+
+  def test_should_yield_no_parameters
+    expectation = new_expectation().yields()
+    yielded_parameters = nil
+    expectation.invoke() { |*parameters| yielded_parameters = parameters }
+    assert_equal Array.new, yielded_parameters
+  end
+
+  def test_should_yield_with_specified_parameters
+    expectation = new_expectation().yields(1, 2, 3)
+    yielded_parameters = nil
+    expectation.invoke() { |*parameters| yielded_parameters = parameters }
+    assert_equal [1, 2, 3], yielded_parameters
+  end
+
+  def test_should_yield_different_parameters_on_consecutive_invocations
+    expectation = new_expectation().yields(1, 2, 3).yields(4, 5)
+    yielded_parameters = []
+    expectation.invoke() { |*parameters| yielded_parameters << parameters }
+    expectation.invoke() { |*parameters| yielded_parameters << parameters }
+    assert_equal [[1, 2, 3], [4, 5]], yielded_parameters
+  end
+  
+  def test_should_yield_multiple_times_for_single_invocation
+    expectation = new_expectation().multiple_yields([1, 2, 3], [4, 5])
+    yielded_parameters = []
+    expectation.invoke() { |*parameters| yielded_parameters << parameters }
+    assert_equal [[1, 2, 3], [4, 5]], yielded_parameters
+  end
+
+  def test_should_yield_multiple_times_for_first_invocation_and_once_for_second_invocation
+    expectation = new_expectation().multiple_yields([1, 2, 3], [4, 5]).then.yields(6, 7)
+    yielded_parameters = []
+    expectation.invoke() { |*parameters| yielded_parameters << parameters }
+    expectation.invoke() { |*parameters| yielded_parameters << parameters }
+    assert_equal [[1, 2, 3], [4, 5], [6, 7]], yielded_parameters
+  end
+
+  def test_should_return_specified_value
+    expectation = new_expectation.returns(99)
+    assert_equal 99, expectation.invoke
+  end
+  
+  def test_should_return_same_specified_value_multiple_times
+    expectation = new_expectation.returns(99)
+    assert_equal 99, expectation.invoke
+    assert_equal 99, expectation.invoke
+  end
+  
+  def test_should_return_specified_values_on_consecutive_calls
+    expectation = new_expectation.returns(99, 100, 101)
+    assert_equal 99, expectation.invoke
+    assert_equal 100, expectation.invoke
+    assert_equal 101, expectation.invoke
+  end
+  
+  def test_should_return_specified_values_on_consecutive_calls_even_if_values_are_modified
+    values = [99, 100, 101]
+    expectation = new_expectation.returns(*values)
+    values.shift
+    assert_equal 99, expectation.invoke
+    assert_equal 100, expectation.invoke
+    assert_equal 101, expectation.invoke
+  end
+  
+  def test_should_return_nil_by_default
+    assert_nil new_expectation.invoke
+  end
+  
+  def test_should_return_nil_if_no_value_specified
+    expectation = new_expectation.returns()
+    assert_nil expectation.invoke
+  end
+  
+  def test_should_return_evaluated_proc
+    proc = lambda { 99 }
+    expectation = new_expectation.returns(proc)
+    result = nil
+    disable_deprecations { result = expectation.invoke }
+    assert_equal 99, result
+  end
+  
+  def test_should_return_evaluated_proc_without_using_is_a_method
+    proc = lambda { 99 }
+    proc.define_instance_accessor(:called)
+    proc.called = false
+    proc.replace_instance_method(:is_a?) { self.called = true; true}
+    expectation = new_expectation.returns(proc)
+    disable_deprecations { expectation.invoke }
+    assert_equal false, proc.called
+  end
+  
+  def test_should_raise_runtime_exception
+    expectation = new_expectation.raises
+    assert_raise(RuntimeError) { expectation.invoke }
+  end
+  
+  def test_should_raise_custom_exception
+    exception = Class.new(Exception)
+    expectation = new_expectation.raises(exception)
+    assert_raise(exception) { expectation.invoke }
+  end
+  
+  def test_should_raise_same_instance_of_custom_exception
+    exception_klass = Class.new(StandardError)
+    expected_exception = exception_klass.new
+    expectation = new_expectation.raises(expected_exception)
+    actual_exception = assert_raise(exception_klass) { expectation.invoke }
+    assert_same expected_exception, actual_exception
+  end
+  
+  def test_should_use_the_default_exception_message
+    expectation = new_expectation.raises(Exception)
+    exception = assert_raise(Exception) { expectation.invoke }
+    assert_equal Exception.new.message, exception.message
+  end
+  
+  def test_should_raise_custom_exception_with_message
+    exception_msg = "exception message"
+    expectation = new_expectation.raises(Exception, exception_msg)
+    exception = assert_raise(Exception) { expectation.invoke }
+    assert_equal exception_msg, exception.message
+  end
+  
+  def test_should_return_values_then_raise_exception
+    expectation = new_expectation.returns(1, 2).then.raises()
+    assert_equal 1, expectation.invoke
+    assert_equal 2, expectation.invoke
+    assert_raise(RuntimeError) { expectation.invoke }
+  end
+  
+  def test_should_raise_exception_then_return_values
+    expectation = new_expectation.raises().then.returns(1, 2)
+    assert_raise(RuntimeError) { expectation.invoke }
+    assert_equal 1, expectation.invoke
+    assert_equal 2, expectation.invoke
+  end
+  
+  def test_should_not_raise_error_on_verify_if_expected_call_was_made
+    expectation = new_expectation
+    expectation.invoke
+    assert_nothing_raised(ExpectationError) {
+      expectation.verify
+    }
+  end
+  
+  def test_should_raise_error_on_verify_if_call_expected_once_but_invoked_twice
+    expectation = new_expectation.once
+    expectation.invoke
+    expectation.invoke
+    assert_raises(ExpectationError) {
+      expectation.verify
+    }
+  end
+
+  def test_should_raise_error_on_verify_if_call_expected_once_but_not_invoked
+    expectation = new_expectation.once
+    assert_raises(ExpectationError) {
+      expectation.verify
+    }
+  end
+
+  def test_should_not_raise_error_on_verify_if_call_expected_once_and_invoked_once
+    expectation = new_expectation.once
+    expectation.invoke
+    assert_nothing_raised(ExpectationError) {
+      expectation.verify
+    }
+  end
+
+  def test_should_not_raise_error_on_verify_if_expected_call_was_made_at_least_once
+    expectation = new_expectation.at_least_once
+    3.times {expectation.invoke}
+    assert_nothing_raised(ExpectationError) {
+      expectation.verify
+    }
+  end
+  
+  def test_should_raise_error_on_verify_if_expected_call_was_not_made_at_least_once
+    expectation = new_expectation.with(1, 2, 3).at_least_once
+    e = assert_raise(ExpectationError) {
+      expectation.verify
+    }
+    assert_match(/expected calls: at least 1, actual calls: 0/i, e.message)
+  end
+  
+  def test_should_not_raise_error_on_verify_if_expected_call_was_made_expected_number_of_times
+    expectation = new_expectation.times(2)
+    2.times {expectation.invoke}
+    assert_nothing_raised(ExpectationError) {
+      expectation.verify
+    }
+  end
+  
+  def test_should_expect_call_not_to_be_made
+    expectation = new_expectation
+    expectation.define_instance_accessor(:how_many_times)
+    expectation.replace_instance_method(:times) { |how_many_times| self.how_many_times = how_many_times }
+    expectation.never
+    assert_equal 0, expectation.how_many_times
+  end
+  
+  def test_should_raise_error_on_verify_if_expected_call_was_made_too_few_times
+    expectation = new_expectation.times(2)
+    1.times {expectation.invoke}
+    e = assert_raise(ExpectationError) {
+      expectation.verify
+    }
+    assert_match(/expected calls: 2, actual calls: 1/i, e.message)
+  end
+  
+  def test_should_raise_error_on_verify_if_expected_call_was_made_too_many_times
+    expectation = new_expectation.times(2)
+    3.times {expectation.invoke}
+    assert_raise(ExpectationError) {
+      expectation.verify
+    }
+  end
+  
+  def test_should_yield_self_to_block
+    expectation = new_expectation
+    expectation.invoke
+    yielded_expectation = nil
+    expectation.verify { |x| yielded_expectation = x }
+    assert_equal expectation, yielded_expectation
+  end
+  
+  def test_should_yield_to_block_before_raising_exception
+    yielded = false
+    assert_raise(ExpectationError) {
+      new_expectation.verify { |x| yielded = true }
+    }
+    assert yielded
+  end
+  
+  def test_should_store_backtrace_from_point_where_expectation_was_created
+    execution_point = ExecutionPoint.current; expectation = Expectation.new(nil, :expected_method)
+    assert_equal execution_point, ExecutionPoint.new(expectation.backtrace)
+  end
+  
+  def test_should_set_backtrace_on_assertion_failed_error_to_point_where_expectation_was_created
+    execution_point = ExecutionPoint.current; expectation = Expectation.new(nil, :expected_method)
+    error = assert_raise(ExpectationError) {  
+      expectation.verify
+    }
+    assert_equal execution_point, ExecutionPoint.new(error.backtrace)
+  end
+  
+  def test_should_display_expectation_in_exception_message
+    options = [:a, :b, {:c => 1, :d => 2}]
+    expectation = new_expectation.with(*options)
+    exception = assert_raise(ExpectationError) { expectation.verify }
+    assert exception.message.include?(expectation.method_signature)
+  end
+  
+  class FakeMock
+    
+    def initialize(name)
+      @name = name
+    end
+
+    def mocha_inspect
+      @name
+    end
+    
+  end
+  
+  def test_should_raise_error_with_message_indicating_which_method_was_expected_to_be_called_on_which_mock_object_with_which_parameters_and_in_what_sequences
+    mock = FakeMock.new('mock')
+    sequence_one = Sequence.new('one')
+    sequence_two = Sequence.new('two')
+    expectation = Expectation.new(mock, :expected_method).with(1, 2, {'a' => true, :b => false}, [1, 2, 3]).in_sequence(sequence_one, sequence_two)
+    e = assert_raise(ExpectationError) { expectation.verify }
+    assert_match "mock.expected_method(1, 2, {'a' => true, :b => false}, [1, 2, 3]); in sequence 'one'; in sequence 'two'", e.message
+  end
+  
+  class FakeConstraint
+    
+    def initialize(allows_invocation_now)
+      @allows_invocation_now = allows_invocation_now
+    end
+    
+    def allows_invocation_now?
+      @allows_invocation_now
+    end
+    
+  end
+  
+  def test_should_be_in_correct_order_if_all_ordering_constraints_allow_invocation_now
+    constraint_one = FakeConstraint.new(allows_invocation_now = true)
+    constraint_two = FakeConstraint.new(allows_invocation_now = true)
+    expectation = Expectation.new(nil, :method_one)
+    expectation.add_ordering_constraint(constraint_one)
+    expectation.add_ordering_constraint(constraint_two)
+    assert expectation.in_correct_order?
+  end
+  
+  def test_should_not_be_in_correct_order_if_one_ordering_constraint_does_not_allow_invocation_now
+    constraint_one = FakeConstraint.new(allows_invocation_now = true)
+    constraint_two = FakeConstraint.new(allows_invocation_now = false)
+    expectation = Expectation.new(nil, :method_one)
+    expectation.add_ordering_constraint(constraint_one)
+    expectation.add_ordering_constraint(constraint_two)
+    assert !expectation.in_correct_order?
+  end
+  
+  def test_should_match_if_all_ordering_constraints_allow_invocation_now
+    constraint_one = FakeConstraint.new(allows_invocation_now = true)
+    constraint_two = FakeConstraint.new(allows_invocation_now = true)
+    expectation = Expectation.new(nil, :method_one)
+    expectation.add_ordering_constraint(constraint_one)
+    expectation.add_ordering_constraint(constraint_two)
+    assert expectation.match?(:method_one)
+  end
+
+  def test_should_not_match_if_one_ordering_constraints_does_not_allow_invocation_now
+    constraint_one = FakeConstraint.new(allows_invocation_now = true)
+    constraint_two = FakeConstraint.new(allows_invocation_now = false)
+    expectation = Expectation.new(nil, :method_one)
+    expectation.add_ordering_constraint(constraint_one)
+    expectation.add_ordering_constraint(constraint_two)
+    assert !expectation.match?(:method_one)
+  end
+
+  def test_should_not_be_satisfied_when_required_invocation_has_not_been_made
+    expectation = Expectation.new(nil, :method_one).times(1)
+    assert !expectation.satisfied?
+  end
+
+  def test_should_be_satisfied_when_required_invocation_has_been_made
+    expectation = Expectation.new(nil, :method_one).times(1)
+    expectation.invoke
+    assert expectation.satisfied?
+  end
+
+  def test_should_not_be_satisfied_when_minimum_number_of_invocations_has_not_been_made
+    expectation = Expectation.new(nil, :method_one).at_least(2)
+    expectation.invoke
+    assert !expectation.satisfied?
+  end
+
+  def test_should_be_satisfied_when_minimum_number_of_invocations_has_been_made
+    expectation = Expectation.new(nil, :method_one).at_least(2)
+    2.times { expectation.invoke }
+    assert expectation.satisfied?
+  end
+  
+  class FakeSequence
+    
+    attr_reader :expectations
+    
+    def initialize
+      @expectations = []
+    end
+    
+    def constrain_as_next_in_sequence(expectation)
+      @expectations << expectation
+    end
+    
+  end
+  
+  def test_should_tell_sequences_to_constrain_expectation_as_next_in_sequence
+    sequence_one = FakeSequence.new
+    sequence_two = FakeSequence.new
+    expectation = Expectation.new(nil, :method_one)
+    assert_equal expectation, expectation.in_sequence(sequence_one, sequence_two)
+    assert_equal [expectation], sequence_one.expectations
+    assert_equal [expectation], sequence_two.expectations
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/hash_inspect_test.rb b/vendor/gems/mocha-0.5.6/test/unit/hash_inspect_test.rb
new file mode 100644
index 0000000..15ad415
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/hash_inspect_test.rb
@@ -0,0 +1,16 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/inspect'
+
+class HashInspectTest < Test::Unit::TestCase
+  
+  def test_should_keep_spacing_between_key_value
+    hash = {:a => true}
+    assert_equal '{:a => true}', hash.mocha_inspect
+  end
+  
+  def test_should_use_mocha_inspect_on_each_item
+    hash = {:a => 'mocha'}
+    assert_equal "{:a => 'mocha'}", hash.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/infinite_range_test.rb b/vendor/gems/mocha-0.5.6/test/unit/infinite_range_test.rb
new file mode 100644
index 0000000..7b4c8a4
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/infinite_range_test.rb
@@ -0,0 +1,53 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/infinite_range'
+require 'date'
+
+class InfiniteRangeTest < Test::Unit::TestCase
+  
+  def test_should_include_values_at_or_above_minimum
+    range = Range.at_least(10)
+    assert(range === 10)
+    assert(range === 11)
+    assert(range === 1000000)
+  end
+  
+  def test_should_not_include_values_below_minimum
+    range = Range.at_least(10)
+    assert_false(range === 0)
+    assert_false(range === 9)
+    assert_false(range === -11)
+  end
+  
+  def test_should_be_human_readable_description_for_at_least
+    assert_equal "at least 10", Range.at_least(10).mocha_inspect
+  end
+  
+  def test_should_include_values_at_or_below_maximum
+    range = Range.at_most(10)
+    assert(range === 10)
+    assert(range === 0)
+    assert(range === -1000000)
+  end
+  
+  def test_should_not_include_values_above_maximum
+    range = Range.at_most(10)
+    assert_false(range === 11)
+    assert_false(range === 1000000)
+  end
+  
+  def test_should_be_human_readable_description_for_at_most
+    assert_equal "at most 10", Range.at_most(10).mocha_inspect
+  end
+  
+  def test_should_be_same_as_standard_to_string
+    assert_equal((1..10).to_s, (1..10).mocha_inspect)
+    assert_equal((1...10).to_s, (1...10).mocha_inspect)
+    date_range = Range.new(Date.parse('2006-01-01'), Date.parse('2007-01-01'))
+    assert_equal date_range.to_s, date_range.mocha_inspect
+  end
+  
+  def assert_false(condition)
+    assert(!condition)
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/metaclass_test.rb b/vendor/gems/mocha-0.5.6/test/unit/metaclass_test.rb
new file mode 100644
index 0000000..956bcb4
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/metaclass_test.rb
@@ -0,0 +1,22 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/metaclass'
+
+class MetaclassTest < Test::Unit::TestCase
+  
+  def test_should_return_objects_singleton_class
+    object = Object.new
+    assert_raises(NoMethodError) { object.success? }
+
+    object = Object.new
+    assert object.__metaclass__.ancestors.include?(Object)
+    assert object.__metaclass__.ancestors.include?(Kernel)
+    assert object.__metaclass__.is_a?(Class)
+
+    object.__metaclass__.class_eval { def success?; true; end }
+    assert object.success?
+    
+    object = Object.new
+    assert_raises(NoMethodError) { object.success? }
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/method_matcher_test.rb b/vendor/gems/mocha-0.5.6/test/unit/method_matcher_test.rb
new file mode 100644
index 0000000..0167433
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/method_matcher_test.rb
@@ -0,0 +1,23 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/method_matcher'
+
+class MethodMatcherTest < Test::Unit::TestCase
+  
+  include Mocha
+
+  def test_should_match_if_actual_method_name_is_same_as_expected_method_name
+    method_matcher = MethodMatcher.new(:method_name)
+    assert method_matcher.match?(:method_name)
+  end
+
+  def test_should_not_match_if_actual_method_name_is_not_same_as_expected_method_name
+    method_matcher = MethodMatcher.new(:method_name)
+    assert !method_matcher.match?(:different_method_name)
+  end
+  
+  def test_should_describe_what_method_is_expected
+    method_matcher = MethodMatcher.new(:method_name)
+    assert_equal "method_name", method_matcher.mocha_inspect
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/missing_expectation_test.rb b/vendor/gems/mocha-0.5.6/test/unit/missing_expectation_test.rb
new file mode 100644
index 0000000..9d3b45a
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/missing_expectation_test.rb
@@ -0,0 +1,42 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/missing_expectation'
+require 'mocha/mock'
+
+class MissingExpectationTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_report_similar_expectations
+    mock = Mock.new
+    expectation_1 = mock.expects(:method_one).with(1)
+    expectation_2 = mock.expects(:method_one).with(1, 1)
+    expectation_3 = mock.expects(:method_two).with(2)
+
+    missing_expectation = MissingExpectation.new(mock, :method_one)
+    exception = assert_raise(ExpectationError) { missing_expectation.verify }
+    
+    expected_message = [
+      "#{missing_expectation.error_message(0, 1)}",
+      "Similar expectations:",
+      "#{expectation_1.method_signature}",
+      "#{expectation_2.method_signature}"
+    ].join("\n")
+    
+    assert_equal expected_message, exception.message
+  end
+  
+  def test_should_not_report_similar_expectations_if_there_are_none
+    mock = Mock.new
+    mock.expects(:method_two).with(2)
+    mock.expects(:method_two).with(2, 2)
+
+    missing_expectation = MissingExpectation.new(mock, :method_one)
+    exception = assert_raise(ExpectationError) { missing_expectation.verify }
+    
+    expected_message = "#{missing_expectation.error_message(0, 1)}"
+    
+    assert_equal expected_message, exception.message
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/mock_test.rb b/vendor/gems/mocha-0.5.6/test/unit/mock_test.rb
new file mode 100644
index 0000000..f844bc8
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/mock_test.rb
@@ -0,0 +1,323 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/mock'
+require 'mocha/expectation_error'
+require 'set'
+
+class MockTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_set_single_expectation
+   mock = Mock.new
+   mock.expects(:method1).returns(1)
+   assert_nothing_raised(ExpectationError) do
+     assert_equal 1, mock.method1
+   end
+  end 
+
+  def test_should_build_and_store_expectations
+   mock = Mock.new
+   expectation = mock.expects(:method1)
+   assert_not_nil expectation
+   assert_equal [expectation], mock.expectations.to_a
+  end
+  
+  def test_should_not_stub_everything_by_default
+    mock = Mock.new
+    assert_equal false, mock.everything_stubbed
+  end
+  
+  def test_should_stub_everything
+    mock = Mock.new
+    mock.stub_everything
+    assert_equal true, mock.everything_stubbed
+  end
+  
+  def test_should_display_object_id_for_mocha_inspect_if_mock_has_no_name
+    mock = Mock.new
+    assert_match Regexp.new("^#<Mock:0x[0-9A-Fa-f]{1,12}>$"), mock.mocha_inspect
+  end
+  
+  def test_should_display_name_for_mocha_inspect_if_mock_has_name
+    mock = Mock.new('named_mock')
+    assert_equal "#<Mock:named_mock>", mock.mocha_inspect
+  end
+
+  def test_should_display_object_id_for_inspect_if_mock_has_no_name
+    mock = Mock.new
+    assert_match Regexp.new("^#<Mock:0x[0-9A-Fa-f]{1,12}>$"), mock.inspect
+  end
+  
+  def test_should_display_name_for_inspect_if_mock_has_name
+    mock = Mock.new('named_mock')
+    assert_equal "#<Mock:named_mock>", mock.inspect
+  end
+
+  def test_should_be_able_to_extend_mock_object_with_module
+    mock = Mock.new
+    assert_nothing_raised(ExpectationError) { mock.extend(Module.new) }
+  end
+  
+  def test_should_be_equal
+    mock = Mock.new
+    assert_equal true, mock.eql?(mock)
+  end
+  
+  if RUBY_VERSION < '1.9'
+    OBJECT_METHODS = STANDARD_OBJECT_PUBLIC_INSTANCE_METHODS.reject { |m| m =~ /^__.*__$/ }
+  else
+    OBJECT_METHODS = STANDARD_OBJECT_PUBLIC_INSTANCE_METHODS.reject { |m| m =~ /^__.*__$/ || m == :object_id }
+  end
+  
+  def test_should_be_able_to_mock_standard_object_methods
+    mock = Mock.new
+    OBJECT_METHODS.each { |method| mock.__expects__(method.to_sym).returns(method) }
+    OBJECT_METHODS.each { |method| assert_equal method, mock.__send__(method.to_sym) }
+    assert_nothing_raised(ExpectationError) { mock.verify }
+  end
+  
+  def test_should_be_able_to_stub_standard_object_methods
+    mock = Mock.new
+    OBJECT_METHODS.each { |method| mock.__stubs__(method.to_sym).returns(method) }
+    OBJECT_METHODS.each { |method| assert_equal method, mock.__send__(method.to_sym) }
+  end
+  
+  def test_should_create_and_add_expectations
+    mock = Mock.new
+    expectation1 = mock.expects(:method1)
+    expectation2 = mock.expects(:method2)
+    assert_equal [expectation1, expectation2].to_set, mock.expectations.to_set
+  end
+  
+  def test_should_pass_backtrace_into_expectation
+    mock = Mock.new
+    backtrace = Object.new
+    expectation = mock.expects(:method1, backtrace)
+    assert_equal backtrace, expectation.backtrace
+  end
+  
+  def test_should_pass_backtrace_into_stub
+    mock = Mock.new
+    backtrace = Object.new
+    stub = mock.stubs(:method1, backtrace)
+    assert_equal backtrace, stub.backtrace
+  end
+  
+  def test_should_create_and_add_stubs
+    mock = Mock.new
+    stub1 = mock.stubs(:method1)
+    stub2 = mock.stubs(:method2)
+    assert_equal [stub1, stub2].to_set, mock.expectations.to_set
+  end
+  
+  def test_should_invoke_expectation_and_return_result
+    mock = Mock.new
+    mock.expects(:my_method).returns(:result)
+    result = mock.my_method
+    assert_equal :result, result
+  end
+  
+  def test_should_not_raise_error_if_stubbing_everything
+    mock = Mock.new
+    mock.stub_everything
+    result = nil
+    assert_nothing_raised(ExpectationError) do
+      result = mock.unexpected_method
+    end
+    assert_nil result
+  end
+  
+  def test_should_raise_assertion_error_for_unexpected_method_call
+    mock = Mock.new
+    error = assert_raise(ExpectationError) do
+      mock.unexpected_method_called(:my_method, :argument1, :argument2)
+    end
+    assert_match(/my_method/, error.message)
+    assert_match(/argument1/, error.message)
+    assert_match(/argument2/, error.message)
+  end
+  
+  def test_should_indicate_unexpected_method_called
+    mock = Mock.new
+    class << mock
+      attr_accessor :symbol, :arguments
+      def unexpected_method_called(symbol, *arguments)
+        self.symbol, self.arguments = symbol, arguments
+      end
+    end
+    mock.my_method(:argument1, :argument2)
+    assert_equal :my_method, mock.symbol
+    assert_equal [:argument1, :argument2], mock.arguments
+  end
+  
+  def test_should_verify_that_all_expectations_have_been_fulfilled
+    mock = Mock.new
+    mock.expects(:method1)
+    mock.expects(:method2)
+    mock.method1
+    assert_raise(ExpectationError) do
+      mock.verify
+    end
+  end
+  
+  def test_should_report_possible_expectations
+    mock = Mock.new
+    mock.expects(:expected_method).with(1)
+    exception = assert_raise(ExpectationError) { mock.expected_method(2) }
+    assert_equal "#{mock.mocha_inspect}.expected_method(2) - expected calls: 0, actual calls: 1\nSimilar expectations:\n#{mock.mocha_inspect}.expected_method(1)", exception.message
+  end
+  
+  def test_should_pass_block_through_to_expectations_verify_method
+    mock = Mock.new
+    expected_expectation = mock.expects(:method1)
+    mock.method1
+    expectations = []
+    mock.verify() { |expectation| expectations << expectation }
+    assert_equal [expected_expectation], expectations
+  end
+  
+  def test_should_yield_supplied_parameters_to_block
+    mock = Mock.new
+    parameters_for_yield = [1, 2, 3]
+    mock.expects(:method1).yields(*parameters_for_yield)
+    yielded_parameters = nil
+    mock.method1() { |*parameters| yielded_parameters = parameters }
+    assert_equal parameters_for_yield, yielded_parameters
+  end
+  
+  def test_should_set_up_multiple_expectations_with_return_values
+    mock = Mock.new
+    mock.expects(:method1 => :result1, :method2 => :result2)
+    assert_equal :result1, mock.method1
+    assert_equal :result2, mock.method2
+  end
+  
+  def test_should_set_up_multiple_stubs_with_return_values
+    mock = Mock.new
+    mock.stubs(:method1 => :result1, :method2 => :result2)
+    assert_equal :result1, mock.method1
+    assert_equal :result2, mock.method2
+  end
+  
+  def test_should_keep_returning_specified_value_for_stubs
+    mock = Mock.new
+    mock.stubs(:method1).returns(1)
+    assert_equal 1, mock.method1
+    assert_equal 1, mock.method1
+  end
+  
+  def test_should_keep_returning_specified_value_for_expects
+    mock = Mock.new
+    mock.expects(:method1).times(2).returns(1)
+    assert_equal 1, mock.method1
+    assert_equal 1, mock.method1
+  end
+  
+  def test_should_match_most_recent_call_to_expects
+    mock = Mock.new
+    mock.expects(:method1).returns(0)
+    mock.expects(:method1).returns(1)
+    assert_equal 1, mock.method1
+  end
+
+  def test_should_match_most_recent_call_to_stubs
+    mock = Mock.new
+    mock.stubs(:method1).returns(0)
+    mock.stubs(:method1).returns(1)
+    assert_equal 1, mock.method1
+  end
+
+  def test_should_match_most_recent_call_to_stubs_or_expects
+    mock = Mock.new
+    mock.stubs(:method1).returns(0)
+    mock.expects(:method1).returns(1)
+    assert_equal 1, mock.method1
+  end
+
+  def test_should_match_most_recent_call_to_expects_or_stubs
+    mock = Mock.new
+    mock.expects(:method1).returns(0)
+    mock.stubs(:method1).returns(1)
+    assert_equal 1, mock.method1
+  end
+  
+  def test_should_respond_to_expected_method
+    mock = Mock.new
+    mock.expects(:method1)
+    assert_equal true, mock.respond_to?(:method1)
+  end
+  
+  def test_should_not_respond_to_unexpected_method
+    mock = Mock.new
+    assert_equal false, mock.respond_to?(:method1)
+  end
+  
+  def test_should_respond_to_methods_which_the_responder_does_responds_to
+    instance = Class.new do
+      define_method(:respond_to?) { |symbol| true }
+    end.new
+    mock = Mock.new
+    mock.responds_like(instance)
+    assert_equal true, mock.respond_to?(:invoked_method)
+  end
+  
+  def test_should_not_respond_to_methods_which_the_responder_does_not_responds_to
+    instance = Class.new do
+      define_method(:respond_to?) { |symbol| false }
+    end.new
+    mock = Mock.new
+    mock.responds_like(instance)
+    assert_equal false, mock.respond_to?(:invoked_method)
+  end
+  
+  def test_should_return_itself_to_allow_method_chaining
+    mock = Mock.new
+    assert_same mock.responds_like(Object.new), mock
+  end
+  
+  def test_should_not_raise_no_method_error_if_mock_is_not_restricted_to_respond_like_a_responder
+    instance = Class.new do
+      define_method(:respond_to?) { true }
+    end.new
+    mock = Mock.new
+    mock.stubs(:invoked_method)
+    assert_nothing_raised(NoMethodError) { mock.invoked_method }
+  end
+  
+  def test_should_not_raise_no_method_error_if_responder_does_respond_to_invoked_method
+    instance = Class.new do
+      define_method(:respond_to?) { |symbol| true }
+    end.new
+    mock = Mock.new
+    mock.responds_like(instance)
+    mock.stubs(:invoked_method)
+    assert_nothing_raised(NoMethodError) { mock.invoked_method }
+  end
+  
+  def test_should_raise_no_method_error_if_responder_does_not_respond_to_invoked_method
+    instance = Class.new do
+      define_method(:respond_to?) { |symbol| false }
+      define_method(:mocha_inspect) { 'mocha_inspect' }
+    end.new
+    mock = Mock.new
+    mock.responds_like(instance)
+    mock.stubs(:invoked_method)
+    assert_raises(NoMethodError) { mock.invoked_method }
+  end
+  
+  def test_should_raise_no_method_error_with_message_indicating_that_mock_is_constrained_to_respond_like_responder
+    instance = Class.new do
+      define_method(:respond_to?) { |symbol| false }
+      define_method(:mocha_inspect) { 'mocha_inspect' }
+    end.new
+    mock = Mock.new
+    mock.responds_like(instance)
+    mock.stubs(:invoked_method)
+    begin
+      mock.invoked_method
+    rescue NoMethodError => e
+      assert_match(/which responds like mocha_inspect/, e.message)
+    end
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/multiple_yields_test.rb b/vendor/gems/mocha-0.5.6/test/unit/multiple_yields_test.rb
new file mode 100644
index 0000000..65724a8
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/multiple_yields_test.rb
@@ -0,0 +1,18 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/multiple_yields'
+
+class MultipleYieldsTest < Test::Unit::TestCase
+  
+  include Mocha
+
+  def test_should_provide_parameters_for_multiple_yields_in_single_invocation
+    parameter_group = MultipleYields.new([1, 2, 3], [4, 5])
+    parameter_groups = []
+    parameter_group.each do |parameters|
+      parameter_groups << parameters
+    end
+    assert_equal [[1, 2, 3], [4, 5]], parameter_groups
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/no_yield_test.rb b/vendor/gems/mocha-0.5.6/test/unit/no_yield_test.rb
new file mode 100644
index 0000000..544d1ef
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/no_yield_test.rb
@@ -0,0 +1,18 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/no_yields'
+
+class NoYieldsTest < Test::Unit::TestCase
+  
+  include Mocha
+
+  def test_should_provide_parameters_for_no_yields_in_single_invocation
+    parameter_group = NoYields.new
+    parameter_groups = []
+    parameter_group.each do |parameters|
+      parameter_groups << parameters
+    end
+    assert_equal [], parameter_groups
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/object_inspect_test.rb b/vendor/gems/mocha-0.5.6/test/unit/object_inspect_test.rb
new file mode 100644
index 0000000..56d84a9
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/object_inspect_test.rb
@@ -0,0 +1,37 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/inspect'
+require 'method_definer'
+
+class ObjectInspectTest < Test::Unit::TestCase
+  
+  def test_should_return_default_string_representation_of_object_not_including_instance_variables
+    object = Object.new
+    class << object
+      attr_accessor :attribute
+    end
+    object.attribute = 'instance_variable'
+    assert_match Regexp.new("^#<Object:0x[0-9A-Fa-f]{1,8}.*>$"), object.mocha_inspect
+    assert_no_match(/instance_variable/, object.mocha_inspect)
+  end
+  
+  def test_should_return_customized_string_representation_of_object
+    object = Object.new
+    class << object
+      define_method(:inspect) { 'custom_inspect' }
+    end
+    assert_equal 'custom_inspect', object.mocha_inspect
+  end
+  
+  def test_should_use_underscored_id_instead_of_object_id_or_id_so_that_they_can_be_stubbed
+    object = Object.new
+    object.define_instance_accessor(:called)
+    object.called = false
+    object.replace_instance_method(:object_id) { self.called = true; 1 }
+    if RUBY_VERSION < '1.9'
+      object.replace_instance_method(:id) { self.called = true; 1 }
+    end
+    object.mocha_inspect
+    assert_equal false, object.called
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/object_test.rb b/vendor/gems/mocha-0.5.6/test/unit/object_test.rb
new file mode 100644
index 0000000..660b7d2
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/object_test.rb
@@ -0,0 +1,165 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/mock'
+require 'method_definer'
+
+require 'mocha/object'
+
+class ObjectTest < Test::Unit::TestCase
+  
+  include Mocha
+    
+  def test_should_build_mocha
+    instance = Object.new
+    mocha = instance.mocha
+    assert_not_nil mocha
+    assert mocha.is_a?(Mock)
+  end
+  
+  def test_should_reuse_existing_mocha
+    instance = Object.new
+    mocha_1 = instance.mocha
+    mocha_2 = instance.mocha
+    assert_equal mocha_1, mocha_2
+  end
+  
+  def test_should_reset_mocha
+    instance = Object.new
+    assert_nil instance.reset_mocha
+  end
+  
+  def test_should_stub_instance_method
+    instance = Object.new
+    $stubba = Mock.new
+    $stubba.expects(:stub).with(Mocha::InstanceMethod.new(instance, :method1))
+    instance.expects(:method1)
+    $stubba.verify
+  end 
+  
+  def test_should_build_and_store_expectation
+    instance = Object.new
+    $stubba = Mock.new
+    $stubba.stubs(:stub)
+    expectation = instance.expects(:method1)
+    assert_equal [expectation], instance.mocha.expectations.to_a
+  end
+  
+  def test_should_verify_expectations
+    instance = Object.new
+    $stubba = Mock.new
+    $stubba.stubs(:stub)
+    instance.expects(:method1).with(:value1, :value2)
+    assert_raise(ExpectationError) { instance.verify }
+  end
+  
+  def test_should_pass_backtrace_into_expects
+    instance = Object.new
+    $stubba = Mock.new
+    $stubba.stubs(:stub)
+    mocha = Object.new
+    mocha.define_instance_accessor(:expects_parameters)
+    mocha.define_instance_method(:expects) { |*parameters| self.expects_parameters = parameters }
+    backtrace = Object.new
+    instance.define_instance_method(:mocha) { mocha }
+    instance.define_instance_method(:caller) { backtrace }
+    instance.expects(:method1)
+    assert_equal [:method1, backtrace], mocha.expects_parameters
+  end
+      
+  def test_should_pass_backtrace_into_stubs
+    instance = Object.new
+    $stubba = Mock.new
+    $stubba.stubs(:stub)
+    mocha = Object.new
+    mocha.define_instance_accessor(:stubs_parameters)
+    mocha.define_instance_method(:stubs) { |*parameters| self.stubs_parameters = parameters }
+    backtrace = Object.new
+    instance.define_instance_method(:mocha) { mocha }
+    instance.define_instance_method(:caller) { backtrace }
+    instance.stubs(:method1)
+    assert_equal [:method1, backtrace], mocha.stubs_parameters
+  end
+      
+  def test_should_build_any_instance_object
+    klass = Class.new
+    any_instance = klass.any_instance
+    assert_not_nil any_instance
+    assert any_instance.is_a?(Class::AnyInstance)
+  end
+  
+  def test_should_return_same_any_instance_object
+    klass = Class.new
+    any_instance_1 = klass.any_instance
+    any_instance_2 = klass.any_instance
+    assert_equal any_instance_1, any_instance_2
+  end
+  
+  def test_should_stub_class_method
+    klass = Class.new
+    $stubba = Mock.new
+    $stubba.expects(:stub).with(Mocha::ClassMethod.new(klass, :method1))
+    klass.expects(:method1)
+    $stubba.verify
+  end 
+  
+  def test_should_build_and_store_class_method_expectation
+    klass = Class.new
+    $stubba = Mock.new
+    $stubba.stubs(:stub)
+    expectation = klass.expects(:method1)
+    assert_equal [expectation], klass.mocha.expectations.to_a
+  end
+  
+  def test_should_stub_module_method
+    mod = Module.new
+    $stubba = Mock.new
+    $stubba.expects(:stub).with(Mocha::ClassMethod.new(mod, :method1))
+    mod.expects(:method1)
+    $stubba.verify
+  end
+  
+  def test_should_build_and_store_module_method_expectation
+    mod = Module.new
+    $stubba = Mock.new
+    $stubba.stubs(:stub)
+    expectation = mod.expects(:method1)
+    assert_equal [expectation], mod.mocha.expectations.to_a
+  end
+  
+  def test_should_use_stubba_instance_method_for_object
+    assert_equal Mocha::InstanceMethod, Object.new.stubba_method
+  end
+    
+  def test_should_use_stubba_class_method_for_module
+    assert_equal Mocha::ClassMethod, Module.new.stubba_method
+  end
+    
+  def test_should_use_stubba_class_method_for_class
+    assert_equal Mocha::ClassMethod, Class.new.stubba_method
+  end
+  
+  def test_should_use_stubba_class_method_for_any_instance
+    assert_equal Mocha::AnyInstanceMethod, Class::AnyInstance.new(nil).stubba_method
+  end
+  
+  def test_should_stub_self_for_object
+    object = Object.new
+    assert_equal object, object.stubba_object
+  end
+      
+  def test_should_stub_self_for_module
+    mod = Module.new
+    assert_equal mod, mod.stubba_object
+  end
+      
+  def test_should_stub_self_for_class
+    klass = Class.new
+    assert_equal klass, klass.stubba_object
+  end
+      
+  def test_should_stub_relevant_class_for_any_instance
+    klass = Class.new
+    any_instance = Class::AnyInstance.new(klass)
+    assert_equal klass, any_instance.stubba_object
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._all_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._all_of_test.rb
new file mode 100644
index 0000000..8494bfb
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._all_of_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._any_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._any_of_test.rb
new file mode 100644
index 0000000..41d4c70
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._any_of_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._anything_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._anything_test.rb
new file mode 100644
index 0000000..bbb511c
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._anything_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_entries_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_entries_test.rb
new file mode 100644
index 0000000..d519eaa
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_entries_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_entry_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_entry_test.rb
new file mode 100644
index 0000000..e38bb38
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_entry_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_key_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_key_test.rb
new file mode 100644
index 0000000..72858bd
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_key_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_value_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_value_test.rb
new file mode 100644
index 0000000..85a2e1c
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._has_value_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._includes_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._includes_test.rb
new file mode 100644
index 0000000..ca7d6d9
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._includes_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._instance_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._instance_of_test.rb
new file mode 100644
index 0000000..14618a7
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._instance_of_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._is_a_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._is_a_test.rb
new file mode 100644
index 0000000..51949f3
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._is_a_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._kind_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._kind_of_test.rb
new file mode 100644
index 0000000..7734378
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._kind_of_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._not_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._not_test.rb
new file mode 100644
index 0000000..d892eab
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._not_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._regexp_matches_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._regexp_matches_test.rb
new file mode 100644
index 0000000..2ceba47
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._regexp_matches_test.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._stub_matcher.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._stub_matcher.rb
new file mode 100644
index 0000000..bc56613
Binary files /dev/null and b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/._stub_matcher.rb differ
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/all_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/all_of_test.rb
new file mode 100644
index 0000000..14028f5
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/all_of_test.rb
@@ -0,0 +1,26 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/all_of'
+require 'mocha/inspect'
+require 'stub_matcher'
+
+class AllOfTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_if_all_matchers_match
+    matcher = all_of(Stub::Matcher.new(true), Stub::Matcher.new(true), Stub::Matcher.new(true))
+    assert matcher.matches?(['any_old_value'])
+  end
+  
+  def test_should_not_match_if_any_matcher_does_not_match
+    matcher = all_of(Stub::Matcher.new(true), Stub::Matcher.new(false), Stub::Matcher.new(true))
+    assert !matcher.matches?(['any_old_value'])
+  end
+  
+  def test_should_describe_matcher
+    matcher = all_of(Stub::Matcher.new(true), Stub::Matcher.new(false), Stub::Matcher.new(true))
+    assert_equal 'all_of(matcher(true), matcher(false), matcher(true))', matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/any_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/any_of_test.rb
new file mode 100644
index 0000000..503d6dc
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/any_of_test.rb
@@ -0,0 +1,26 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/any_of'
+require 'mocha/inspect'
+require 'stub_matcher'
+
+class AnyOfTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_if_any_matchers_match
+    matcher = any_of(Stub::Matcher.new(false), Stub::Matcher.new(true), Stub::Matcher.new(false))
+    assert matcher.matches?(['any_old_value'])
+  end
+  
+  def test_should_not_match_if_no_matchers_match
+    matcher = any_of(Stub::Matcher.new(false), Stub::Matcher.new(false), Stub::Matcher.new(false))
+    assert !matcher.matches?(['any_old_value'])
+  end
+  
+  def test_should_describe_matcher
+    matcher = any_of(Stub::Matcher.new(false), Stub::Matcher.new(true), Stub::Matcher.new(false))
+    assert_equal 'any_of(matcher(false), matcher(true), matcher(false))', matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/anything_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/anything_test.rb
new file mode 100644
index 0000000..42a88a1
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/anything_test.rb
@@ -0,0 +1,21 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/anything'
+require 'mocha/inspect'
+
+class AnythingTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_anything
+    matcher = anything
+    assert matcher.matches?([:something])
+    assert matcher.matches?([{'x' => 'y'}])
+  end
+  
+  def test_should_describe_matcher
+    matcher = anything
+    assert_equal "anything", matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_entries_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_entries_test.rb
new file mode 100644
index 0000000..cb85265
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_entries_test.rb
@@ -0,0 +1,30 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/has_entries'
+require 'mocha/inspect'
+
+class HasEntriesTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_hash_including_specified_entries
+    matcher = has_entries(:key_1 => 'value_1', :key_2 => 'value_2')
+    assert matcher.matches?([{ :key_1 => 'value_1', :key_2 => 'value_2', :key_3 => 'value_3' }])
+  end
+  
+  def test_should_not_match_hash_not_including_specified_entries
+    matcher = has_entries(:key_1 => 'value_2', :key_2 => 'value_2', :key_3 => 'value_3')
+    assert !matcher.matches?([{ :key_1 => 'value_1', :key_2 => 'value_2' }])
+  end
+  
+  def test_should_describe_matcher
+    matcher = has_entries(:key_1 => 'value_1', :key_2 => 'value_2')
+    description = matcher.mocha_inspect
+    matches = /has_entries\((.*)\)/.match(description)
+    assert_not_nil matches[0]
+    entries = eval(matches[1])
+    assert_equal 'value_1', entries[:key_1]
+    assert_equal 'value_2', entries[:key_2]
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_entry_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_entry_test.rb
new file mode 100644
index 0000000..3717b33
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_entry_test.rb
@@ -0,0 +1,40 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/has_entry'
+require 'mocha/inspect'
+
+class HasEntryTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_hash_including_specified_key_value_pair
+    matcher = has_entry(:key_1, 'value_1')
+    assert matcher.matches?([{ :key_1 => 'value_1', :key_2 => 'value_2' }])
+  end
+  
+  def test_should_not_match_hash_not_including_specified_key_value_pair
+    matcher = has_entry(:key_1, 'value_2')
+    assert !matcher.matches?([{ :key_1 => 'value_1', :key_2 => 'value_2' }])
+  end
+  
+  def test_should_match_hash_including_specified_entry
+    matcher = has_entry(:key_1 => 'value_1')
+    assert matcher.matches?([{ :key_1 => 'value_1', :key_2 => 'value_2' }])
+  end
+  
+  def test_should_not_match_hash_not_including_specified_entry
+    matcher = has_entry(:key_1 => 'value_2')
+    assert !matcher.matches?([{ :key_1 => 'value_1', :key_2 => 'value_2' }])
+  end
+  
+  def test_should_describe_matcher_with_key_value_pair
+    matcher = has_entry(:key_1, 'value_1')
+    assert_equal "has_entry(:key_1, 'value_1')", matcher.mocha_inspect
+  end
+  
+  def test_should_describe_matcher_with_entry
+    matcher = has_entry(:key_1 => 'value_1')
+    assert_equal "has_entry(:key_1, 'value_1')", matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_key_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_key_test.rb
new file mode 100644
index 0000000..bc9f506
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_key_test.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/has_key'
+require 'mocha/inspect'
+
+class HasKeyTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_hash_including_specified_key
+    matcher = has_key(:key_1)
+    assert matcher.matches?([{ :key_1 => 1, :key_2 => 2 }])
+  end
+  
+  def test_should_not_match_hash_not_including_specified_key
+    matcher = has_key(:key_1)
+    assert !matcher.matches?([{ :key_2 => 2 }])
+  end
+  
+  def test_should_describe_matcher
+    matcher = has_key(:key)
+    assert_equal 'has_key(:key)', matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_value_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_value_test.rb
new file mode 100644
index 0000000..6c8957f
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/has_value_test.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/has_value'
+require 'mocha/inspect'
+
+class HasValueTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_hash_including_specified_value
+    matcher = has_value('value_1')
+    assert matcher.matches?([{ :key_1 => 'value_1', :key_2 => 'value_2' }])
+  end
+  
+  def test_should_not_match_hash_not_including_specified_value
+    matcher = has_value('value_1')
+    assert !matcher.matches?([{ :key_2 => 'value_2' }])
+  end
+  
+  def test_should_describe_matcher
+    matcher = has_value('value_1')
+    assert_equal "has_value('value_1')", matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/includes_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/includes_test.rb
new file mode 100644
index 0000000..70fb649
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/includes_test.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/includes'
+require 'mocha/inspect'
+
+class IncludesTest < Test::Unit::TestCase
+
+  include Mocha::ParameterMatchers
+
+  def test_should_match_object_including_value
+    matcher = includes(:x)
+    assert matcher.matches?([[:x, :y, :z]])
+  end
+
+  def test_should_not_match_object_that_does_not_include_value
+    matcher = includes(:not_included)
+    assert !matcher.matches?([[:x, :y, :z]])
+  end
+
+  def test_should_describe_matcher
+    matcher = includes(:x)
+    assert_equal "includes(:x)", matcher.mocha_inspect
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/instance_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/instance_of_test.rb
new file mode 100644
index 0000000..415b79a
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/instance_of_test.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/instance_of'
+require 'mocha/inspect'
+
+class InstanceOfTest < Test::Unit::TestCase
+
+  include Mocha::ParameterMatchers
+
+  def test_should_match_object_that_is_an_instance_of_specified_class
+    matcher = instance_of(String)
+    assert matcher.matches?(['string'])
+  end
+
+  def test_should_not_match_object_that_is_not_an_instance_of_specified_class
+    matcher = instance_of(String)
+    assert !matcher.matches?([99])
+  end
+
+  def test_should_describe_matcher
+    matcher = instance_of(String)
+    assert_equal "instance_of(String)", matcher.mocha_inspect
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/is_a_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/is_a_test.rb
new file mode 100644
index 0000000..c9ef919
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/is_a_test.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/is_a'
+require 'mocha/inspect'
+
+class IsATest < Test::Unit::TestCase
+
+  include Mocha::ParameterMatchers
+
+  def test_should_match_object_that_is_a_specified_class
+    matcher = is_a(Integer)
+    assert matcher.matches?([99])
+  end
+
+  def test_should_not_match_object_that_is_not_a_specified_class
+    matcher = is_a(Integer)
+    assert !matcher.matches?(['string'])
+  end
+
+  def test_should_describe_matcher
+    matcher = is_a(Integer)
+    assert_equal "is_a(Integer)", matcher.mocha_inspect
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/kind_of_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/kind_of_test.rb
new file mode 100644
index 0000000..1167e5c
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/kind_of_test.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/kind_of'
+require 'mocha/inspect'
+
+class KindOfTest < Test::Unit::TestCase
+
+  include Mocha::ParameterMatchers
+
+  def test_should_match_object_that_is_a_kind_of_specified_class
+    matcher = kind_of(Integer)
+    assert matcher.matches?([99])
+  end
+
+  def test_should_not_match_object_that_is_not_a_kind_of_specified_class
+    matcher = kind_of(Integer)
+    assert !matcher.matches?(['string'])
+  end
+
+  def test_should_describe_matcher
+    matcher = kind_of(Integer)
+    assert_equal "kind_of(Integer)", matcher.mocha_inspect
+  end
+
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/not_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/not_test.rb
new file mode 100644
index 0000000..4cb6790
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/not_test.rb
@@ -0,0 +1,26 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/not'
+require 'mocha/inspect'
+require 'stub_matcher'
+
+class NotTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_if_matcher_does_not_match
+    matcher = Not(Stub::Matcher.new(false))
+    assert matcher.matches?(['any_old_value'])
+  end
+  
+  def test_should_not_match_if_matcher_does_match
+    matcher = Not(Stub::Matcher.new(true))
+    assert !matcher.matches?(['any_old_value'])
+  end
+  
+  def test_should_describe_matcher
+    matcher = Not(Stub::Matcher.new(true))
+    assert_equal 'Not(matcher(true))', matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/regexp_matches_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/regexp_matches_test.rb
new file mode 100644
index 0000000..a8294bf
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/regexp_matches_test.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), "..", "..", "test_helper")
+
+require 'mocha/parameter_matchers/regexp_matches'
+require 'mocha/inspect'
+
+class MatchesTest < Test::Unit::TestCase
+  
+  include Mocha::ParameterMatchers
+  
+  def test_should_match_parameter_matching_regular_expression
+    matcher = regexp_matches(/oo/)
+    assert matcher.matches?(['foo'])
+  end
+  
+  def test_should_not_match_parameter_not_matching_regular_expression
+    matcher = regexp_matches(/oo/)
+    assert !matcher.matches?(['bar'])
+  end
+  
+  def test_should_describe_matcher
+    matcher = regexp_matches(/oo/)
+    assert_equal "regexp_matches(/oo/)", matcher.mocha_inspect
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/stub_matcher.rb b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/stub_matcher.rb
new file mode 100644
index 0000000..920ced2
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameter_matchers/stub_matcher.rb
@@ -0,0 +1,23 @@
+module Stub
+  
+  class Matcher
+
+    attr_accessor :value
+
+    def initialize(matches)
+      @matches = matches
+    end
+
+    def matches?(available_parameters)
+      value = available_parameters.shift
+      @value = value
+      @matches
+    end
+
+    def mocha_inspect
+      "matcher(#{@matches})"
+    end
+
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/parameters_matcher_test.rb b/vendor/gems/mocha-0.5.6/test/unit/parameters_matcher_test.rb
new file mode 100644
index 0000000..612805e
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/parameters_matcher_test.rb
@@ -0,0 +1,121 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/parameters_matcher'
+
+class ParametersMatcherTest < Test::Unit::TestCase
+  
+  include Mocha
+
+  def test_should_match_any_actual_parameters_if_no_expected_parameters_specified
+    parameters_matcher = ParametersMatcher.new
+    assert parameters_matcher.match?(actual_parameters = [1, 2, 3])
+  end
+
+  def test_should_match_if_actual_parameters_are_same_as_expected_parameters
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, 6])
+    assert parameters_matcher.match?(actual_parameters = [4, 5, 6])
+  end
+  
+  def test_should_not_match_if_actual_parameters_are_different_from_expected_parameters
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, 6])
+    assert !parameters_matcher.match?(actual_parameters = [1, 2, 3])
+  end
+  
+  def test_should_not_match_if_there_are_less_actual_parameters_than_expected_parameters
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, 6])
+    assert !parameters_matcher.match?(actual_parameters = [4, 5])
+  end
+  
+  def test_should_not_match_if_there_are_more_actual_parameters_than_expected_parameters
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5])
+    assert !parameters_matcher.match?(actual_parameters = [4, 5, 6])
+  end
+  
+  def test_should_not_match_if_not_all_required_parameters_are_supplied
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert !parameters_matcher.match?(actual_parameters = [4])
+  end
+  
+  def test_should_match_if_all_required_parameters_match_and_no_optional_parameters_are_supplied
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert parameters_matcher.match?(actual_parameters = [4, 5])
+  end
+  
+  def test_should_match_if_all_required_and_optional_parameters_match_and_some_optional_parameters_are_supplied
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert parameters_matcher.match?(actual_parameters = [4, 5, 6])
+  end
+  
+  def test_should_match_if_all_required_and_optional_parameters_match_and_all_optional_parameters_are_supplied
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert parameters_matcher.match?(actual_parameters = [4, 5, 6, 7])
+  end
+  
+  def test_should_not_match_if_all_required_and_optional_parameters_match_but_too_many_optional_parameters_are_supplied
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert !parameters_matcher.match?(actual_parameters = [4, 5, 6, 7, 8])
+  end
+  
+  def test_should_not_match_if_all_required_parameters_match_but_some_optional_parameters_do_not_match
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert !parameters_matcher.match?(actual_parameters = [4, 5, 6, 0])
+  end
+
+  def test_should_not_match_if_some_required_parameters_do_not_match_although_all_optional_parameters_do_match
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert !parameters_matcher.match?(actual_parameters = [4, 0, 6])
+  end
+
+  def test_should_not_match_if_all_required_parameters_match_but_no_optional_parameters_match
+    optionals = ParameterMatchers::Optionally.new(6, 7)
+    parameters_matcher = ParametersMatcher.new(expected_parameters = [4, 5, optionals])
+    assert !parameters_matcher.match?(actual_parameters = [4, 5, 0, 0])
+  end
+
+  def test_should_match_if_actual_parameters_satisfy_matching_block
+    parameters_matcher = ParametersMatcher.new { |x, y| x + y == 3 }
+    assert parameters_matcher.match?(actual_parameters = [1, 2])
+  end
+
+  def test_should_not_match_if_actual_parameters_do_not_satisfy_matching_block
+    parameters_matcher = ParametersMatcher.new { |x, y| x + y == 3 }
+    assert !parameters_matcher.match?(actual_parameters = [2, 3])
+  end
+  
+  def test_should_remove_outer_array_braces
+    params = [1, 2, [3, 4]]
+    parameters_matcher = ParametersMatcher.new(params)
+    assert_equal '(1, 2, [3, 4])', parameters_matcher.mocha_inspect
+  end
+  
+  def test_should_display_numeric_arguments_as_is
+    params = [1, 2, 3]
+    parameters_matcher = ParametersMatcher.new(params)
+    assert_equal '(1, 2, 3)', parameters_matcher.mocha_inspect
+  end
+  
+  def test_should_remove_curly_braces_if_hash_is_only_argument
+    params = [{:a => 1, :z => 2}]
+    parameters_matcher = ParametersMatcher.new(params)
+    assert_nil parameters_matcher.mocha_inspect.index('{')
+    assert_nil parameters_matcher.mocha_inspect.index('}')
+  end
+  
+  def test_should_not_remove_curly_braces_if_hash_is_not_the_only_argument
+    params = [1, {:a => 1}]
+    parameters_matcher = ParametersMatcher.new(params)
+    assert_equal '(1, {:a => 1})', parameters_matcher.mocha_inspect
+  end
+  
+  def test_should_indicate_that_matcher_will_match_any_actual_parameters
+    parameters_matcher = ParametersMatcher.new
+    assert_equal '(any_parameters)', parameters_matcher.mocha_inspect
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/return_values_test.rb b/vendor/gems/mocha-0.5.6/test/unit/return_values_test.rb
new file mode 100644
index 0000000..01ddfbc
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/return_values_test.rb
@@ -0,0 +1,63 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/return_values'
+
+class ReturnValuesTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_return_nil
+    values = ReturnValues.new
+    assert_nil values.next
+  end
+
+  def test_should_keep_returning_nil
+    values = ReturnValues.new
+    values.next
+    assert_nil values.next
+    assert_nil values.next
+  end
+
+  def test_should_return_evaluated_single_return_value
+    values = ReturnValues.new(SingleReturnValue.new('value'))
+    assert_equal 'value', values.next
+  end
+
+  def test_should_keep_returning_evaluated_single_return_value
+    values = ReturnValues.new(SingleReturnValue.new('value'))
+    values.next
+    assert_equal 'value', values.next
+    assert_equal 'value', values.next
+  end
+
+  def test_should_return_consecutive_evaluated_single_return_values
+    values = ReturnValues.new(SingleReturnValue.new('value_1'), SingleReturnValue.new('value_2'))
+    assert_equal 'value_1', values.next
+    assert_equal 'value_2', values.next
+  end
+
+  def test_should_keep_returning_last_of_consecutive_evaluated_single_return_values
+    values = ReturnValues.new(SingleReturnValue.new('value_1'), SingleReturnValue.new('value_2'))
+    values.next
+    values.next
+    assert_equal 'value_2', values.next
+    assert_equal 'value_2', values.next
+  end
+  
+  def test_should_build_single_return_values_for_each_values
+    values = ReturnValues.build('value_1', 'value_2', 'value_3').values
+    assert_equal 'value_1', values[0].evaluate
+    assert_equal 'value_2', values[1].evaluate
+    assert_equal 'value_3', values[2].evaluate
+  end
+  
+  def test_should_combine_two_sets_of_return_values
+    values_1 = ReturnValues.build('value_1')
+    values_2 = ReturnValues.build('value_2a', 'value_2b')
+    values = (values_1 + values_2).values
+    assert_equal 'value_1', values[0].evaluate
+    assert_equal 'value_2a', values[1].evaluate
+    assert_equal 'value_2b', values[2].evaluate
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/sequence_test.rb b/vendor/gems/mocha-0.5.6/test/unit/sequence_test.rb
new file mode 100644
index 0000000..544b3fe
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/sequence_test.rb
@@ -0,0 +1,104 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/sequence'
+require 'mocha/expectation'
+
+class SequenceTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  class FakeExpectation
+    
+    attr_reader :ordering_constraints
+    
+    def initialize(satisfied = false)
+      @satisfied = satisfied
+      @ordering_constraints = []
+    end
+    
+    def add_ordering_constraint(ordering_constraint)
+      @ordering_constraints << ordering_constraint
+    end
+    
+    def satisfied?
+      @satisfied
+    end
+    
+  end
+  
+  def test_should_be_satisfied_if_no_expectations_added
+    sequence = Sequence.new('name')
+    assert sequence.satisfied_to_index?(0)
+  end
+
+  def test_should_be_satisfied_if_one_unsatisfied_expectations_added_but_it_is_not_included_by_index
+    sequence = Sequence.new('name')
+    expectation = FakeExpectation.new(satisfied = false)
+    sequence.constrain_as_next_in_sequence(expectation)
+    assert sequence.satisfied_to_index?(0)
+  end
+
+  def test_should_not_be_satisfied_if_one_unsatisfied_expectations_added_and_it_is_included_by_index
+    sequence = Sequence.new('name')
+    expectation = FakeExpectation.new(satisfied = false)
+    sequence.constrain_as_next_in_sequence(expectation)
+    assert !sequence.satisfied_to_index?(1)
+  end
+
+  def test_should_be_satisfied_if_one_satisfied_expectations_added_and_it_is_included_by_index
+    sequence = Sequence.new('name')
+    expectation = FakeExpectation.new(satisfied = true)
+    sequence.constrain_as_next_in_sequence(expectation)
+    assert sequence.satisfied_to_index?(1)
+  end
+
+  def test_should_not_be_satisfied_if_one_satisfied_and_one_unsatisfied_expectation_added_and_both_are_included_by_index
+    sequence = Sequence.new('name')
+    expectation_one = FakeExpectation.new(satisfied = true)
+    expectation_two = FakeExpectation.new(satisfied = false)
+    sequence.constrain_as_next_in_sequence(expectation_one)
+    sequence.constrain_as_next_in_sequence(expectation_two)
+    assert !sequence.satisfied_to_index?(2)
+  end
+
+  def test_should_be_satisfied_if_two_satisfied_expectations_added_and_both_are_included_by_index
+    sequence = Sequence.new('name')
+    expectation_one = FakeExpectation.new(satisfied = true)
+    expectation_two = FakeExpectation.new(satisfied = true)
+    sequence.constrain_as_next_in_sequence(expectation_one)
+    sequence.constrain_as_next_in_sequence(expectation_two)
+    assert sequence.satisfied_to_index?(2)
+  end
+  
+  def test_should_add_ordering_constraint_to_expectation
+    sequence = Sequence.new('name')
+    expectation = FakeExpectation.new
+    sequence.constrain_as_next_in_sequence(expectation)
+    assert_equal 1, expectation.ordering_constraints.length
+  end
+
+  def test_should_not_allow_invocation_of_second_method_when_first_n_sequence_has_not_been_invoked
+    sequence = Sequence.new('name')
+    expectation_one = FakeExpectation.new(satisfied = false)
+    expectation_two = FakeExpectation.new(satisfied = false)
+    sequence.constrain_as_next_in_sequence(expectation_one)
+    sequence.constrain_as_next_in_sequence(expectation_two)
+    assert !expectation_two.ordering_constraints[0].allows_invocation_now?
+  end
+
+  def test_should_allow_invocation_of_second_method_when_first_in_sequence_has_been_invoked
+    sequence = Sequence.new('name')
+    expectation_one = FakeExpectation.new(satisfied = true)
+    expectation_two = FakeExpectation.new(satisfied = false)
+    sequence.constrain_as_next_in_sequence(expectation_one)
+    sequence.constrain_as_next_in_sequence(expectation_two)
+    assert expectation_two.ordering_constraints[0].allows_invocation_now?
+  end
+
+  def test_should_describe_ordering_constraint_as_being_part_of_named_sequence
+    sequence = Sequence.new('wibble')
+    expectation = FakeExpectation.new
+    sequence.constrain_as_next_in_sequence(expectation)
+    assert_equal "in sequence 'wibble'", expectation.ordering_constraints[0].mocha_inspect
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/setup_and_teardown_test.rb b/vendor/gems/mocha-0.5.6/test/unit/setup_and_teardown_test.rb
new file mode 100644
index 0000000..8324788
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/setup_and_teardown_test.rb
@@ -0,0 +1,76 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/mock'
+
+require 'mocha/setup_and_teardown'
+
+class SetupAndTeardownTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_instantiate_new_stubba
+    test_case = stubbed_test_case_class.new
+    test_case.setup_stubs
+    
+    assert $stubba
+    assert $stubba.is_a?(Mocha::Central)
+  end
+
+  def test_should_verify_all_expectations
+    test_case = stubbed_test_case_class.new
+    stubba = Mock.new
+    stubba.expects(:verify_all)
+    $stubba = stubba
+    
+    test_case.verify_stubs
+    
+    stubba.verify
+  end
+
+  def test_should_yield_to_block_for_each_assertion
+    test_case = stubbed_test_case_class.new
+    $stubba = Mock.new
+    $stubba.stubs(:verify_all).yields
+    yielded = false
+    
+    test_case.verify_stubs { yielded = true }
+    
+    assert_equal true, yielded
+  end
+
+  def test_should_unstub_all_stubbed_methods
+    test_case = stubbed_test_case_class.new
+    stubba = Mock.new
+    stubba.expects(:unstub_all)
+    $stubba = stubba
+    
+    test_case.teardown_stubs
+    
+    stubba.verify
+  end
+
+  def test_should_set_stubba_to_nil
+    test_case = stubbed_test_case_class.new
+    $stubba = Mock.new
+    $stubba.stubs(:unstub_all)
+
+    test_case.teardown_stubs
+    
+    assert_nil $stubba
+  end
+  
+  def test_should_not_raise_exception_if_no_stubba_central_available
+    test_case = stubbed_test_case_class.new
+    $stubba = nil
+    assert_nothing_raised { test_case.teardown_stubs }
+  end
+  
+  private
+  
+  def stubbed_test_case_class
+    Class.new do
+      include Mocha::SetupAndTeardown
+    end
+  end
+
+end
+
diff --git a/vendor/gems/mocha-0.5.6/test/unit/single_return_value_test.rb b/vendor/gems/mocha-0.5.6/test/unit/single_return_value_test.rb
new file mode 100644
index 0000000..9d3d799
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/single_return_value_test.rb
@@ -0,0 +1,33 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/single_return_value'
+require 'deprecation_disabler'
+
+class SingleReturnValueTest < Test::Unit::TestCase
+  
+  include Mocha
+  include DeprecationDisabler
+  
+  def test_should_return_value
+    value = SingleReturnValue.new('value')
+    assert_equal 'value', value.evaluate
+  end
+  
+  def test_should_return_result_of_calling_proc
+    proc = lambda { 'value' }
+    value = SingleReturnValue.new(proc)
+    result = nil
+    disable_deprecations { result = value.evaluate }
+    assert_equal 'value', result
+  end
+  
+  def test_should_indicate_deprecated_use_of_expectation_returns_method
+    proc = lambda {}
+    value = SingleReturnValue.new(proc)
+    Deprecation.messages = []
+    disable_deprecations { value.evaluate }
+    expected_message = "use of Expectation#returns with instance of Proc - see Expectation#returns RDoc for alternatives"
+    assert_equal [expected_message], Deprecation.messages
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/single_yield_test.rb b/vendor/gems/mocha-0.5.6/test/unit/single_yield_test.rb
new file mode 100644
index 0000000..12bd0a2
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/single_yield_test.rb
@@ -0,0 +1,18 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/single_yield'
+
+class SingleYieldTest < Test::Unit::TestCase
+  
+  include Mocha
+
+  def test_should_provide_parameters_for_single_yield_in_single_invocation
+    parameter_group = SingleYield.new(1, 2, 3)
+    parameter_groups = []
+    parameter_group.each do |parameters|
+      parameter_groups << parameters
+    end
+    assert_equal [[1, 2, 3]], parameter_groups
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/string_inspect_test.rb b/vendor/gems/mocha-0.5.6/test/unit/string_inspect_test.rb
new file mode 100644
index 0000000..43b9c4e
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/string_inspect_test.rb
@@ -0,0 +1,11 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/inspect'
+
+class StringInspectTest < Test::Unit::TestCase
+  
+  def test_should_replace_escaped_quotes_with_single_quote
+    string = "my_string"
+    assert_equal "'my_string'", string.mocha_inspect
+  end
+  
+end
diff --git a/vendor/gems/mocha-0.5.6/test/unit/stub_test.rb b/vendor/gems/mocha-0.5.6/test/unit/stub_test.rb
new file mode 100644
index 0000000..a225963
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/stub_test.rb
@@ -0,0 +1,24 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+require 'mocha/stub'
+
+class StubTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_always_verify_successfully
+    stub = Stub.new(nil, :expected_method)
+    assert stub.verify
+    stub.invoke
+    assert stub.verify
+  end
+  
+  def test_should_match_successfully_for_any_number_of_invocations
+    stub = Stub.new(nil, :expected_method)
+    assert stub.match?(:expected_method)
+    stub.invoke
+    assert stub.match?(:expected_method)
+    stub.invoke
+    assert stub.match?(:expected_method)
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/mocha-0.5.6/test/unit/yield_parameters_test.rb b/vendor/gems/mocha-0.5.6/test/unit/yield_parameters_test.rb
new file mode 100644
index 0000000..4e93f13
--- /dev/null
+++ b/vendor/gems/mocha-0.5.6/test/unit/yield_parameters_test.rb
@@ -0,0 +1,93 @@
+require File.join(File.dirname(__FILE__), "..", "test_helper")
+
+require 'mocha/yield_parameters'
+require 'mocha/no_yields'
+require 'mocha/single_yield'
+require 'mocha/multiple_yields'
+
+class YieldParametersTest < Test::Unit::TestCase
+  
+  include Mocha
+  
+  def test_should_return_null_yield_parameter_group_by_default
+    yield_parameters = YieldParameters.new
+    assert yield_parameters.next_invocation.is_a?(NoYields)
+  end
+  
+  def test_should_return_single_yield_parameter_group
+    yield_parameters = YieldParameters.new
+    yield_parameters.add(1, 2, 3)
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(SingleYield)
+    assert_equal [1, 2, 3], parameter_group.parameters
+  end
+  
+  def test_should_keep_returning_single_yield_parameter_group
+    yield_parameters = YieldParameters.new
+    yield_parameters.add(1, 2, 3)
+    yield_parameters.next_invocation
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(SingleYield)
+    assert_equal [1, 2, 3], parameter_group.parameters
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(SingleYield)
+    assert_equal [1, 2, 3], parameter_group.parameters
+  end
+  
+  def test_should_return_consecutive_single_yield_parameter_groups
+    yield_parameters = YieldParameters.new
+    yield_parameters.add(1, 2, 3)
+    yield_parameters.add(4, 5)
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(SingleYield)
+    assert_equal [1, 2, 3], parameter_group.parameters
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(SingleYield)
+    assert_equal [4, 5], parameter_group.parameters
+  end
+  
+  def test_should_return_multiple_yield_parameter_group
+    yield_parameters = YieldParameters.new
+    yield_parameters.multiple_add([1, 2, 3], [4, 5])
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(MultipleYields)
+    assert_equal [[1, 2, 3], [4, 5]], parameter_group.parameter_groups
+  end
+  
+  def test_should_keep_returning_multiple_yield_parameter_group
+    yield_parameters = YieldParameters.new
+    yield_parameters.multiple_add([1, 2, 3], [4, 5])
+    yield_parameters.next_invocation
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(MultipleYields)
+    assert_equal [[1, 2, 3], [4, 5]], parameter_group.parameter_groups
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(MultipleYields)
+    assert_equal [[1, 2, 3], [4, 5]], parameter_group.parameter_groups
+  end
+  
+  def test_should_return_consecutive_multiple_yield_parameter_groups
+    yield_parameters = YieldParameters.new
+    yield_parameters.multiple_add([1, 2, 3], [4, 5])
+    yield_parameters.multiple_add([6, 7], [8, 9, 0])
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(MultipleYields)
+    assert_equal [[1, 2, 3], [4, 5]], parameter_group.parameter_groups
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(MultipleYields)
+    assert_equal [[6, 7], [8, 9, 0]], parameter_group.parameter_groups
+  end
+  
+  def test_should_return_consecutive_single_and_multiple_yield_parameter_groups
+    yield_parameters = YieldParameters.new
+    yield_parameters.add(1, 2, 3)
+    yield_parameters.multiple_add([4, 5, 6], [7, 8])
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(SingleYield)
+    assert_equal [1, 2, 3], parameter_group.parameters
+    parameter_group = yield_parameters.next_invocation
+    assert parameter_group.is_a?(MultipleYields)
+    assert_equal [[4, 5, 6], [7, 8]], parameter_group.parameter_groups
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/CHANGES b/vendor/gems/rspec/CHANGES
new file mode 100644
index 0000000..887c9d8
--- /dev/null
+++ b/vendor/gems/rspec/CHANGES
@@ -0,0 +1,1045 @@
+== Version 1.1.3
+
+Maintenance release.
+
+* Tightened up exceptions list in autotest/rails_spec. Closes #264.
+* Applied patch from Ryan Davis for ZenTest-3.9.0 compatibility
+* Applied patch from Kero to add step_upcoming to story listeners. Closes #253.
+* Fixed bug where the wrong named error was not always caught by "should raise_error"
+* Applied patch from Luis Lavena: No coloured output on Windows due missing RUBYOPT. Closes #244.
+* Applied patch from Craig Demyanovich to add support for "should_not render_template" to rspec_on_rails. Closes #241.
+* Added --pattern (-p for short) option to control what files get loaded. Defaults to '**/*_spec.rb'
+* Exit with non-0 exit code if examples *or tests* (in test/unit interop mode) fail. Closes #203.
+* Moved at_exit hook to a method in Spec::Runner which only runs if specs get loaded. Closes #242.
+* Applied patch from kakutani ensuring that base_view_path gets cleared after each view example. Closes #235.
+* More tweaks to regexp step names
+* Fixed focused specs in nested ExampleGroups. Closes #225.
+
+== Version 1.1.2
+
+Minor bug fixes/enhancements.
+
+* RSpec's Autotest subclasses compatible with ZenTest-3.8.0 (thanks to Ryan Davis for making it easier on Autotest subs).
+* Applied patch from idl to add spec/lib to rake stats. Closes #226.
+* calling setup_fixtures and teardown_fixtures for Rails >= r8570. Closes #219.
+* Applied patch from Josh Knowles using ActiveSupport's Inflector (when available) to make 'should have' read a bit better. Closes #197.
+* Fixed regression in 1.1 that caused failing examples to fail to generate their own names. Closes #209.
+* Applied doc patch from Jens Krämer for capturing content_for
+* Applied patch from Alexander Lang to clean up story steps after each story. Closes #198.
+* Applied patch from Josh Knowles to support 'string_or_response.should have_text(...)'. Closes #193.
+* Applied patch from Ian Dees to quiet the Story Runner backtrace. Closes #183.
+* Complete support for defining steps with regexp 'names'.
+
+== Version 1.1.1
+
+Bug fix release.
+
+* Fix regression in 1.1.0 that caused transactions to not get rolled back between examples.
+* Applied patch from Bob Cotton to reintroduce ExampleGroup.description_options. Closes LH[#186]
+
+== Version 1.1.0
+
+The "tell me a story and go nest yourself" release.
+
+* Applied patch from Mike Vincent to handle generators rails > 2.0.1. Closes LH[#181]
+* Formatter.pending signature changed so it gets passed an ExampleGroup instance instead of the name ( LH[#180])
+* Fixed LH[#180] Spec::Rails::Example::ModelExampleGroup and friends show up in rspec/rails output
+* Spec::Rails no longer loads ActiveRecord extensions if it's disabled in config/boot.rb
+* Applied LH[#178] small annoyances running specs with warnings enabled (Patch from Mikko Lehtonen)
+* Tighter integration with Rails fixtures. Take advantage of fixture caching to get performance improvements (Thanks to Pat Maddox, Nick Kallen, Jonathan Barnes, and Curtis)
+
+== Version 1.1.0-RC1
+
+Textmate Bundle users - this release adds a new RSpec bundle that highlights describe, it, before and after and
+provides navigation to descriptions and examples (rather than classes and methods). When you first install this,
+it is going to try to hijack all of your .rb files. All you need to do is open a .rb file that does not end with
+'spec.rb' and change the bundle selection from RSpec to Ruby. TextMate will do the right thing from then on.
+
+Shortcuts for tab-activated snippets all follow the TextMate convention of 2 or 3 letters of the first word, followed by the first letter of each subsequent word. So "should have_at_least" would be triggered by shhal.
+
+We reduced the scope for running spec directories, files, a single file or individual spec in TextMate to source.ruby.rspec. This allowed us to restore the standard Ruby shortcuts:
+
+CMD-R runs all the specs in one file
+CMD-SHIFT-R runs an individual spec
+CMD-OPT-R runs any files or directories selected in the TextMate drawer
+
+rspec_on_rails users - don't forget to run script/generate rspec
+
+* Added shared_examples_for method, which you can (should) use instead of describe Foo, :shared => true
+* Applied LH[#168] Fix describe Object, "description contains a # in it" (Patch from Martin Emde)
+* Applied LH[#15] Reverse loading of ActionView::Base helper modules (Patch from Mark Van Holstyn)
+* Applied LH[#149] Update contribute page to point towards lighthouse (Patch from Josh Knowles)
+* Applied LH[#142] verify_rcov fails with latest rcov (Patch from Kyle Hargraves)
+* Applied LH[#10] Allow stubs to yield and return values (Patch from Pat Maddox)
+* Fixed LH[#139] version.rb in trunk missing svn last changed number
+* Applied LH[#14] Adding support for by_at_least/by_at_most in Change matcher (Patch from Saimon Moore)
+* Applied LH[#12] Fix for TM when switching to alternate file (Patch from Trevor Squires)
+* Applied LH[#133] ExampleMatcher should match against before(:all) (Patch from Bob Cotton)
+* Applied LH[#134] Only load spec inside spec_helper.rb (Patch from Mark Van Holstyn)
+* RSpec now bails immediately if there are examples with identical names.
+* Applied LH[#132]  Plain Text stories should support Given and Given: (Patch from Jarkko Laine)
+* Applied patch from Pat Maddox: Story Mediator - the glue that binds the plain text story parser with the rest of the system
+* Applied LH[#16] Have SimpleMatchers expose their description for specdocs (Patch from Bryan Helmkamp)
+* Stories now support --colour
+* Changed the DSL modules to Example (i.e. Spec::Example instead of Spec::DSL)
+* Applied [#15608] Story problem if parenthesis used in Given, When, Then or And (Patch from Sinclair Bain)
+* Applied [#15659] GivenScenario fails when it is a RailsStory (Patch from Nathan Sutton)
+* Fixed [#15639] rcov exclusion configuration. (Spec::Rails projects can configure rcov with spec/rcov.opts)
+* The rdoc formatter (--format rdoc) is gone. It was buggy and noone was using it.
+* Changed Spec::DSL::Behaviour to Spec::DSL::ExampleGroup
+* Changed Spec::DSL::SharedBehaviour to Spec::DSL::SharedExampleGroup
+* Applied [#14023] Small optimization for heavily proxied objects. (Patch from Ian Leitch)
+* Applied [#13943] ProfileFormatter (Top 10 slowest examples) (Patch from Ian Leitch)
+* Fixed [#15232] heckle is not working correctly in trunk (as of r2801)
+* Applied [#14399] Show pending reasons in HTML report (Patch from Bryan Helmkamp)
+* Discovered fixed: [#10263] mock "leak" when setting an expectation in a block passed to mock#should_receive
+* Fixed [#14671] Spec::DSL::ExampleRunner gives "NO NAME because of --dry-run" for every example for 'rake spec:doc'
+* Fixed [#14543] rspec_scaffold broken with Rails 2.0
+* Removed Patch [#10577] Rails with Oracle breaks 0.9.2 - was no longer necessary since we moved describe to the Main object (instead of Object)
+* Fixed [#14527] specs run twice on rails 1.2.4 and rspec/rspec_on_rails trunk
+* Applied [#14043] Change output ordering to show pending before errors (Patch from Mike Mangino)
+* Applied [#14095] Don't have ./script/generate rspec create previous_failures.txt (Patch from Bryan Helmkamp)
+* Applied [#14254] Improved error handling for Object#should and Object#should_not (Patch from Antti Tarvainen)
+* Applied [#14186] Remove dead code from message_expecation.rb (Patch from Antti Tarvainen)
+* Applied [#14183] Tiny improvement on mock_spec.rb (Patch from Antti Tarvainen)
+* Applied [#14208] Fix to Mock#method_missing raising NameErrors instead of MockExpectationErrors (Patch from Antti Tarvainen)
+* Applied [#14255] Fixed examples in mock_spec.rb and shared_behaviour_spec.rb (Patch from Antti Tarvainen)
+* Applied [#14362] partially mocking objects that define == can blow up (Patch from Pat Maddox)
+* test_ methods with an arity of 0 defined in a describe block or Example object will be run as an Example, providing a seamless transition from Test::Unit
+* Removed BehaviourRunner
+* Fixed [#13969] Spec Failures on Trunk w/ Autotest
+* Applied [#14156] False positives with should_not (Patch from Antti Tarvainen)
+* Applied [#14170] route_for and params_from internal specs fixed (Patch from Antti Tarvainen)
+* Fixed [#14166] Cannot build trunk
+* Applied [#14142] Fix for bug #11602: Nested #have_tag specifications fails on the wrong line number (Patch from Antti Tarvainen)
+* Removed warn_if_no_files argument and feature
+* Steps (Given/When/Then) with no blocks are treated as pending
+* Applied [#13913] Scenario should treat no code block as pending (Patch from Evan Light)
+* Fixed [#13370] Weird mock expectation error (Patch from Mike Mangino)
+* Applied [#13952] Fix for performance regression introduced in r2096 (Patch from Ian Leitch)
+* Applied [#13881] Dynamically include Helpers that are included on ActionView::Base (Patch from Brandon Keepers)
+* Applied [#13833] ActionView::Helpers::JavaScriptMacrosHelper removed after 1.2.3 (Patch from Yurii Rashkovskii)
+* Applied [#13814] RSpec on Rails w/ fixture-scenarios (Patch from Shintaro Kakutani)
+* Add ability to define Example subclass instead of using describe
+* Applied Patch from James Edward Gray II to improve syntax highlighting in TextMate
+* Fixed [#13579] NoMethodError not raised for missing helper methods
+* Fixed [#13713] form helper method 'select' can not be called when calling custom helper methods from specs
+* Example subclasses Test::Unit::TestCase
+* Added stub_everything method to create a stub that will return itself for any message it doesn't understand
+* Added stories directory with stories/all.rb and stories/helper.rb when you script/generate rspec
+* Applied [#13554] Add "And" so you can say Given... And... When... Then... And...
+* Applied [#11254] RSpec syntax coloring and function pop-up integration in TextMate (Patch from Wincent Colaiuta)
+* Applied [#13143] ActionView::Helpers::RecordIdentificationHelper should be included if present (Patch from Jay Levitt)
+* Applied [#13567] patch to allow stubs to yield consecutive values (Patch from Rupert Voelcker)
+* Applied [#13559] reverse version of route_for (Patch from Rupert Voelcker)
+* Added [#13532] /lib specs should get base EvalContext
+* Applied [#13451] Add a null_object option to mock_model (Patch from James Deville)
+* Applied [#11919] Making non-implemented specs easy in textmate (Patch from Scott Taylor)
+* Applied [#13274] ThrowSymbol recognized a NameError triggered by Kernel#method_missing as a thrown Symbol
+* Applied [#12722] the alternate file command does not work in rails views due to scope (Patch from Carl Porth)
+* Behaviour is now a Module that is used by Example class methods and SharedBehaviour
+* Added ExampleDefinition
+* Added story runner framework based on rbehave [#12628]
+* Applied [#13336] Helper directory incorrect for rake stats in statsetup task (Patch from Curtis Miller)
+* Applied [#13339] Add the ability for spec_parser to parse describes with :behaviour_type set (Patch from Will Leinweber and Dav Yaginuma)
+* Fixed [#13271] incorrect behaviour with expect_render and stub_render
+* Applied [#13129] Fix failing specs in spec_distributed (Patch from Bob Cotton)
+* Applied [#13118] Rinda support for Spec::Distributed (Patch from Bob Cotton)
+* Removed BehaviourEval
+* Removed Behaviour#inherit
+* Moved implementation of install_dependencies to example_rails_app
+* Renamed RSPEC_DEPS to VENDOR_DEPS
+* Added Example#not_implemented?
+* You can now stub!(:msg).with(specific args)
+* describe("A", Hash, "with one element") will generate description "A Hash with one element" (Tip from Ola Bini)
+* Applied [#13016] [DOC] Point out that view specs render, well, a view (Patch from Jay Levitt)
+* Applied [#13078] Develop rspec with autotest (Patch from Scott Taylor)
+* Fixed [#13065] Named routes throw a NoMethodError in Helper specs (Patches from James Deville and Mike Mangino)
+* Added (back) the verbose attribute in Spec::Rake::SpecTask
+* Changed documentation to point at the new http svn URL, which is more accessible.
+
+== 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 Kr�mer)
+* 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 ViewExampleGroupController (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/MIT-LICENSE b/vendor/gems/rspec/MIT-LICENSE
new file mode 100644
index 0000000..1d11ea5
--- /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 0000000..0683b0d
--- /dev/null
+++ b/vendor/gems/rspec/README
@@ -0,0 +1,71 @@
+== RSpec
+
+RSpec is a Behaviour Driven Development framework with tools to express User Stories
+with Executable Scenarios and Executable Examples at the code level.
+
+RSpec ships with several modules:
+
+Spec::Story provides a framework for expressing User Stories
+
+Spec::Example provides a framework for expressing code Examples
+
+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.
+
+== 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
+* webby         # Generates the static HTML website
+* syntax        # Required 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.
+
+== Contributing
+
diff --git a/vendor/gems/rspec/Rakefile b/vendor/gems/rspec/Rakefile
new file mode 100644
index 0000000..c60d5d4
--- /dev/null
+++ b/vendor/gems/rspec/Rakefile
@@ -0,0 +1,279 @@
+$:.unshift('lib')
+require 'rubygems'
+require 'rake/gempackagetask'
+require 'rake/contrib/rubyforgepublisher'
+require 'rake/clean'
+require 'rake/rdoctask'
+require 'rake/testtask'
+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_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/**/*',
+  'examples/**/*',
+  'failing_examples/**/*',
+  'plugins/**/*',
+  'stories/**/*',
+  'pre_commit/**/*',
+  'rake_tasks/**/*'
+]
+
+task :default => [:verify_rcov]
+task :verify_rcov => [:spec, :stories]
+
+desc "Run all specs"
+Spec::Rake::SpecTask.new do |t|
+  t.spec_files = FileList['spec/**/*_spec.rb']
+  t.spec_opts = ['--options', 'spec/spec.opts']
+  unless ENV['NO_RCOV']
+    t.rcov = true
+    t.rcov_dir = '../doc/output/coverage'
+    t.rcov_opts = ['--exclude', 'spec\/spec,bin\/spec,examples,\/var\/lib\/gems,\/Library\/Ruby,\.autotest']
+  end
+end
+
+desc "Run all stories"
+task :stories do
+  html = 'story_server/prototype/rspec_stories.html'
+  ruby "stories/all.rb --colour --format plain --format html:#{html}"
+  unless IO.read(html) =~ /<span class="param">/m
+    raise 'highlighted parameters are broken in story HTML'
+  end
+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', '../../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 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', 'UPGRADE', 'lib/**/*.rb')
+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.bindir = 'bin'
+  s.executables = ['spec', 'spec_translator']
+  s.default_executable = 'spec'
+  s.author = "RSpec Development Team"
+  s.email = "rspec-devel at rubyforge.org"
+  s.homepage = "http://rspec.rubyforge.org"
+  s.platform = Gem::Platform::RUBY
+  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_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) {core.rdoc_rails}
+
+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 at 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 at 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 "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
+  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"
+  ]
+  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 at 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/TODO b/vendor/gems/rspec/TODO
new file mode 100644
index 0000000..250bb66
--- /dev/null
+++ b/vendor/gems/rspec/TODO
@@ -0,0 +1,2 @@
+=== Before releasing 1.1.0:
+
diff --git a/vendor/gems/rspec/UPGRADE b/vendor/gems/rspec/UPGRADE
new file mode 100644
index 0000000..0a2c6f5
--- /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/vendor/gems/rspec/bin/spec b/vendor/gems/rspec/bin/spec
new file mode 100755
index 0000000..283176d
--- /dev/null
+++ b/vendor/gems/rspec/bin/spec
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
+require 'spec'
+exit ::Spec::Runner::CommandLine.run(rspec_options)
diff --git a/vendor/gems/rspec/bin/spec_translator b/vendor/gems/rspec/bin/spec_translator
new file mode 100755
index 0000000..abd50b7
--- /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/pure/autogenerated_docstrings_example.rb b/vendor/gems/rspec/examples/pure/autogenerated_docstrings_example.rb
new file mode 100644
index 0000000..a4928ef
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/autogenerated_docstrings_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/pure/before_and_after_example.rb b/vendor/gems/rspec/examples/pure/before_and_after_example.rb
new file mode 100644
index 0000000..7db6274
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/before_and_after_example.rb
@@ -0,0 +1,40 @@
+require File.dirname(__FILE__) + '/spec_helper'
+$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/pure/behave_as_example.rb b/vendor/gems/rspec/examples/pure/behave_as_example.rb
new file mode 100755
index 0000000..e95d146
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/custom_expectation_matchers.rb b/vendor/gems/rspec/examples/pure/custom_expectation_matchers.rb
new file mode 100644
index 0000000..075bb54
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/custom_formatter.rb b/vendor/gems/rspec/examples/pure/custom_formatter.rb
new file mode 100644
index 0000000..c449fdc
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/custom_formatter.rb
@@ -0,0 +1,12 @@
+require File.dirname(__FILE__) + '/spec_helper'
+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/pure/dynamic_spec.rb b/vendor/gems/rspec/examples/pure/dynamic_spec.rb
new file mode 100644
index 0000000..15d473d
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/file_accessor.rb b/vendor/gems/rspec/examples/pure/file_accessor.rb
new file mode 100644
index 0000000..ff6fb74
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/file_accessor.rb
@@ -0,0 +1,19 @@
+require File.dirname(__FILE__) + '/spec_helper'
+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/pure/file_accessor_spec.rb b/vendor/gems/rspec/examples/pure/file_accessor_spec.rb
new file mode 100644
index 0000000..628d4c0
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/greeter_spec.rb b/vendor/gems/rspec/examples/pure/greeter_spec.rb
new file mode 100644
index 0000000..ec7669d
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/greeter_spec.rb
@@ -0,0 +1,31 @@
+require File.dirname(__FILE__) + '/spec_helper'
+# 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/pure/helper_method_example.rb b/vendor/gems/rspec/examples/pure/helper_method_example.rb
new file mode 100644
index 0000000..d97f19e
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/helper_method_example.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+module HelperMethodExample
+  describe "an example group 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
+end
+
diff --git a/vendor/gems/rspec/examples/pure/io_processor.rb b/vendor/gems/rspec/examples/pure/io_processor.rb
new file mode 100644
index 0000000..6b15147
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/io_processor_spec.rb b/vendor/gems/rspec/examples/pure/io_processor_spec.rb
new file mode 100644
index 0000000..5cab7bf
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/legacy_spec.rb b/vendor/gems/rspec/examples/pure/legacy_spec.rb
new file mode 100644
index 0000000..c863695
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/legacy_spec.rb
@@ -0,0 +1,11 @@
+require File.dirname(__FILE__) + '/spec_helper'
+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/pure/mocking_example.rb b/vendor/gems/rspec/examples/pure/mocking_example.rb
new file mode 100644
index 0000000..6adbef5
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/multi_threaded_behaviour_runner.rb b/vendor/gems/rspec/examples/pure/multi_threaded_behaviour_runner.rb
new file mode 100644
index 0000000..36edcd4
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/multi_threaded_behaviour_runner.rb
@@ -0,0 +1,28 @@
+class MultiThreadedExampleGroupRunner < Spec::Runner::ExampleGroupRunner
+  def initialize(options, arg)
+    super(options)
+    # configure these
+    @thread_count = 4
+    @thread_wait = 0
+  end
+
+  def run
+    @threads = []
+    q = Queue.new
+    example_groups.each { |b| q << b}
+    success = true
+    @thread_count.times do
+      @threads << Thread.new(q) do |queue|
+        while not queue.empty?
+          example_group = queue.pop
+          success &= example_group.suite.run(nil)
+        end
+      end
+      sleep @thread_wait
+    end
+    @threads.each {|t| t.join}
+    success
+  end
+end
+
+MultiThreadedBehaviourRunner = MultiThreadedExampleGroupRunner
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/pure/nested_classes_example.rb b/vendor/gems/rspec/examples/pure/nested_classes_example.rb
new file mode 100644
index 0000000..abe43b0
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/nested_classes_example.rb
@@ -0,0 +1,36 @@
+require File.dirname(__FILE__) + '/spec_helper'
+require File.dirname(__FILE__) + '/stack'
+
+class StackExamples < Spec::ExampleGroup
+  describe(Stack)
+  before(:each) do
+    @stack = Stack.new
+  end
+end
+
+class EmptyStackExamples < StackExamples
+  describe("when empty")
+  it "should be empty" do
+    @stack.should be_empty
+  end
+end
+
+class AlmostFullStackExamples < StackExamples
+  describe("when almost full")
+  before(:each) do
+    (1..9).each {|n| @stack.push n}
+  end
+  it "should be full" do
+    @stack.should_not be_full
+  end
+end
+
+class FullStackExamples < StackExamples
+  describe("when full")
+  before(:each) do
+    (1..10).each {|n| @stack.push n}
+  end
+  it "should be full" do
+    @stack.should be_full
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/pure/partial_mock_example.rb b/vendor/gems/rspec/examples/pure/partial_mock_example.rb
new file mode 100644
index 0000000..841ec88
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/pending_example.rb b/vendor/gems/rspec/examples/pure/pending_example.rb
new file mode 100644
index 0000000..13f3d00
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/predicate_example.rb b/vendor/gems/rspec/examples/pure/predicate_example.rb
new file mode 100644
index 0000000..1202bb6
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/priority.txt b/vendor/gems/rspec/examples/pure/priority.txt
new file mode 100644
index 0000000..5b00064
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/priority.txt
@@ -0,0 +1 @@
+examples/custom_expectation_matchers.rb
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/pure/shared_example_group_example.rb b/vendor/gems/rspec/examples/pure/shared_example_group_example.rb
new file mode 100644
index 0000000..fb81af1
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/shared_example_group_example.rb
@@ -0,0 +1,81 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+module SharedExampleGroupExample
+  class OneThing
+    def what_things_do
+      "stuff"
+    end
+  end
+  
+  class AnotherThing
+    def what_things_do
+      "stuff"
+    end
+  end
+  
+  class YetAnotherThing
+    def what_things_do
+      "stuff"
+    end
+  end
+  
+  # A SharedExampleGroup is an example group that doesn't get run.
+  # You can create one like this:
+  share_examples_for "most things" do
+    def helper_method
+      "helper method"
+    end
+    
+    it "should do what things do" do
+      @thing.what_things_do.should == "stuff"
+    end
+  end
+
+  # A SharedExampleGroup is also module. If you create one like this
+  # it gets assigned to the constant AllThings
+  share_as :MostThings 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
+    # Now you can include the shared example group like this, which 
+    # feels more like what you might say ...
+    it_should_behave_like "most things"
+    
+    before(:each) { @thing = OneThing.new }
+    
+    it "should have access to helper methods defined in the shared example group" do
+      helper_method.should == "helper method"
+    end
+  end
+
+  describe AnotherThing do
+    # ... or you can include the example group like this, which
+    # feels more like the programming language we love.
+    it_should_behave_like MostThings
+    
+    before(:each) { @thing = AnotherThing.new }
+
+    it "should have access to helper methods defined in the shared example group" do
+      helper_method.should == "helper method"
+    end
+  end
+
+  describe YetAnotherThing do
+    # ... or you can include the example group like this, which
+    # feels more like the programming language we love.
+    include MostThings
+    
+    before(:each) { @thing = AnotherThing.new }
+
+    it "should have access to helper methods defined in the shared example group" do
+      helper_method.should == "helper method"
+    end
+  end
+end
diff --git a/vendor/gems/rspec/examples/pure/shared_stack_examples.rb b/vendor/gems/rspec/examples/pure/shared_stack_examples.rb
new file mode 100644
index 0000000..7a08162
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/shared_stack_examples.rb
@@ -0,0 +1,38 @@
+require File.join(File.dirname(__FILE__), *%w[spec_helper])
+
+shared_examples_for "non-empty Stack" do
+
+  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
+
+shared_examples_for "non-full Stack" do
+
+  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
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/pure/spec_helper.rb b/vendor/gems/rspec/examples/pure/spec_helper.rb
new file mode 100644
index 0000000..1e88079
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/spec_helper.rb
@@ -0,0 +1,3 @@
+lib_path = File.expand_path("#{File.dirname(__FILE__)}/../../lib")
+$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
+require 'spec'
diff --git a/vendor/gems/rspec/examples/pure/stack.rb b/vendor/gems/rspec/examples/pure/stack.rb
new file mode 100644
index 0000000..407173f
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/pure/stack_spec.rb b/vendor/gems/rspec/examples/pure/stack_spec.rb
new file mode 100644
index 0000000..2a769da
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/stack_spec.rb
@@ -0,0 +1,63 @@
+require File.dirname(__FILE__) + '/spec_helper'
+require File.dirname(__FILE__) + "/stack"
+require File.dirname(__FILE__) + '/shared_stack_examples'
+
+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/pure/stack_spec_with_nested_example_groups.rb b/vendor/gems/rspec/examples/pure/stack_spec_with_nested_example_groups.rb
new file mode 100644
index 0000000..05f6ad4
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/stack_spec_with_nested_example_groups.rb
@@ -0,0 +1,67 @@
+require File.dirname(__FILE__) + '/spec_helper'
+require File.dirname(__FILE__) + '/stack'
+require File.dirname(__FILE__) + '/shared_stack_examples'
+
+describe Stack do
+  
+  before(:each) do
+    @stack = Stack.new
+  end
+
+  describe "(empty)" do
+
+    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 "(with one item)" do
+    
+    before(:each) do
+      @stack.push 3
+      @last_item_added = 3
+    end
+
+    it_should_behave_like "non-empty Stack"
+    it_should_behave_like "non-full Stack"
+
+  end
+
+  describe "(with one item less than capacity)" do
+    
+    before(:each) do
+      (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 "(full)" do
+    
+    before(:each) do
+      (1..10).each { |i| @stack.push i }
+      @last_item_added = 10
+    end
+
+    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
+
+end
diff --git a/vendor/gems/rspec/examples/pure/stubbing_example.rb b/vendor/gems/rspec/examples/pure/stubbing_example.rb
new file mode 100644
index 0000000..31354ae
--- /dev/null
+++ b/vendor/gems/rspec/examples/pure/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/stories/adder.rb b/vendor/gems/rspec/examples/stories/adder.rb
new file mode 100644
index 0000000..0b027b0
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/adder.rb
@@ -0,0 +1,13 @@
+class Adder
+  def initialize
+    @addends = []
+  end
+  
+  def <<(val)
+    @addends << val
+  end
+  
+  def sum
+    @addends.inject(0) { |sum_so_far, val| sum_so_far + val }
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/stories/addition b/vendor/gems/rspec/examples/stories/addition
new file mode 100644
index 0000000..58f0929
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/addition
@@ -0,0 +1,34 @@
+This is a story about a calculator. The text up here above the Story: declaration
+won't be processed, so you can write whatever you wish!
+
+Story: simple addition
+
+  As an accountant
+  I want to add numbers
+  So that I can count beans
+
+  Scenario: add one plus one
+    Given an addend of 1
+    And an addend of 1
+    
+    When the addends are addeds
+    
+    Then the sum should be 3
+    And the corks should be popped
+  
+  Scenario: add two plus five
+    Given an addend of 2
+    And an addend of 5
+    
+    When the addends are added
+    
+    Then the sum should be 7
+    Then it should snow
+    
+  Scenario: add three more
+    GivenScenario add two plus five
+    And an addend of 3
+    
+    When the addends are added
+    
+    Then the sum should be 10
diff --git a/vendor/gems/rspec/examples/stories/addition.rb b/vendor/gems/rspec/examples/stories/addition.rb
new file mode 100644
index 0000000..e43f5cf
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/addition.rb
@@ -0,0 +1,9 @@
+require File.join(File.dirname(__FILE__), "helper")
+require File.join(File.dirname(__FILE__), "adder")
+
+# with_steps_for :addition, :more_addition do
+with_steps_for :addition, :more_addition do
+  # Then("the corks should be popped") { }
+  run File.expand_path(__FILE__).gsub(".rb","")
+end
+
diff --git a/vendor/gems/rspec/examples/stories/calculator.rb b/vendor/gems/rspec/examples/stories/calculator.rb
new file mode 100644
index 0000000..390437c
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/calculator.rb
@@ -0,0 +1,65 @@
+$:.push File.join(File.dirname(__FILE__), *%w[.. .. lib])
+require 'spec'
+
+class AdditionMatchers < Spec::Story::StepGroup
+  steps do |add|
+    add.given("an addend of $addend") do |addend|
+      @adder ||= Adder.new
+      @adder << addend.to_i
+    end
+  end
+end
+
+steps = AdditionMatchers.new do |add|  
+  add.then("the sum should be $sum") do |sum|
+    @sum.should == sum.to_i
+  end
+end
+
+steps.when("they are added") do
+  @sum = @adder.sum
+end
+
+# This Story uses steps (see above) instead of blocks
+# passed to Given, When and Then
+
+Story "addition", %{
+  As an accountant
+  I want to add numbers
+  So that I can count some beans
+}, :steps => steps do
+  Scenario "2 + 3" do
+    Given "an addend of 2"
+    And "an addend of 3"
+    When "they are added"
+    Then "the sum should be 5"
+  end
+  
+  # This scenario uses GivenScenario, which silently runs
+  # all the steps in a previous scenario.
+  
+  Scenario "add 4 more" do
+    GivenScenario "2 + 3"
+    Given "an addend of 4"
+    When "they are added"
+    Then "the sum should be 9"
+  end
+end
+
+# And the class that makes the story pass
+
+class Adder
+  def << addend
+    addends << addend
+  end
+  
+  def sum
+    @addends.inject(0) do |result, addend|
+      result + addend.to_i
+    end
+  end
+  
+  def addends
+    @addends ||= []
+  end
+end
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/README.txt b/vendor/gems/rspec/examples/stories/game-of-life/README.txt
new file mode 100644
index 0000000..9624ad4
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/README.txt
@@ -0,0 +1,21 @@
+John Conway's Game of Life
+
+The Rules
+---------
+The Game of Life was invented by John Conway (as you might have gathered).
+The game is played on a field of cells, each of which has eight neighbors (adjacent cells).
+A cell is either occupied (by an organism) or not.
+The rules for deriving a generation from the previous one are these:
+
+Survival
+--------
+If an occupied cell has 2 or 3 neighbors, the organism survives to the next generation.
+
+Death
+-----
+If an occupied cell has 0, 1, 4, 5, 6, 7, or 8 occupied neighbors, the organism dies
+(0, 1: of loneliness; 4 thru 8: of overcrowding).
+
+Birth
+-----
+If an unoccupied cell has 3 occupied neighbors, it becomes occupied.
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/everything.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/everything.rb
new file mode 100644
index 0000000..90a281d
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/everything.rb
@@ -0,0 +1,6 @@
+$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib')
+$:.unshift File.join(File.dirname(__FILE__), '..')
+
+require 'spec'
+require 'behaviour/examples/examples'
+require 'behaviour/stories/stories'
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/examples.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/examples.rb
new file mode 100644
index 0000000..1cadfb3
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/examples.rb
@@ -0,0 +1,3 @@
+require 'spec'
+require 'behaviour/examples/game_behaviour'
+require 'behaviour/examples/grid_behaviour'
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/game_behaviour.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/game_behaviour.rb
new file mode 100644
index 0000000..ff5b357
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/game_behaviour.rb
@@ -0,0 +1,35 @@
+require 'life'
+
+describe Game do
+  it 'should have a grid' do
+    # given
+    game = Game.new(5, 5)
+    
+    # then
+    game.grid.should be_kind_of(Grid)
+  end
+  
+  it 'should create a cell' do
+    # given
+    game = Game.new(2, 2)
+    expected_grid = Grid.from_string( 'X. ..' )
+    
+    # when
+    game.create_at(0, 0)
+    
+    # then
+    game.grid.should == expected_grid
+  end
+  
+  it 'should destroy a cell' do
+    # given
+    game = Game.new(2,2)
+    game.grid = Grid.from_string('X. ..')
+    
+    # when
+    game.destroy_at(0,0)
+    
+    # then
+    game.grid.should == Grid.from_string('.. ..')
+  end
+end
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/grid_behaviour.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/grid_behaviour.rb
new file mode 100644
index 0000000..5be3af5
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/examples/grid_behaviour.rb
@@ -0,0 +1,66 @@
+describe Grid do
+  it 'should be empty when created' do
+    # given
+    expected_contents = [
+      [0, 0, 0],
+      [0, 0, 0]
+    ]
+    grid = Grid.new(2, 3)
+    
+    # when
+    contents = grid.contents
+    
+    # then
+    contents.should == expected_contents
+  end
+  
+  it 'should compare equal based on its contents' do
+    # given
+    grid1 = Grid.new(2, 3)
+    grid2 = Grid.new(2, 3)
+    
+    # then
+    grid1.should == grid2
+  end
+  
+  it 'should be able to replace its contents' do
+    # given
+    grid = Grid.new(2,2)
+    new_contents = [[0,1,0], [1,0,1]]
+    
+    # when
+    grid.contents = new_contents
+    
+    # then
+    grid.contents.should == new_contents
+    grid.rows.should == 2
+    grid.columns.should == 3
+  end
+  
+  it 'should add an organism' do
+    # given
+    grid = Grid.new(2, 2)
+    expected = Grid.new(2, 2)
+    expected.contents = [[1,0],[0,0]]
+    
+    # when
+    grid.create_at(0,0)
+    
+    # then
+    grid.should == expected
+  end
+  
+  it 'should create itself from a string' do
+    # given
+    expected = Grid.new 3, 3
+    expected.create_at(0,0)
+    expected.create_at(1,0)
+    expected.create_at(2,2)
+    
+    # when
+    actual = Grid.from_string "X.. X.. ..X"
+    
+    # then
+    actual.should == expected
+  end
+end
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/CellsWithLessThanTwoNeighboursDie.story b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/CellsWithLessThanTwoNeighboursDie.story
new file mode 100644
index 0000000..8374e86
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/CellsWithLessThanTwoNeighboursDie.story
@@ -0,0 +1,21 @@
+Story: cells with less than two neighbours die
+
+As a game producer
+I want cells with less than two neighbours to die
+So that I can illustrate how the game works to people with money
+
+Scenario: cells with zero or one neighbour die
+
+Given the grid looks like
+........
+.XX.XX..
+.XX.....
+....X...
+........
+When the next step occurs
+Then the grid should look like
+........
+.XX.....
+.XX.....
+........
+........
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/CellsWithMoreThanThreeNeighboursDie.story b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/CellsWithMoreThanThreeNeighboursDie.story
new file mode 100644
index 0000000..0d30b59
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/CellsWithMoreThanThreeNeighboursDie.story
@@ -0,0 +1,21 @@
+Story: cells with more than three neighbours die
+
+As a game producer
+I want cells with more than three neighbours to die
+So that I can show the people with money how we are getting on
+
+Scenario: blink
+
+Given the grid looks like
+.....
+...XX
+...XX
+.XX..
+.XX..
+When the next step occurs
+Then the grid should look like
+.....
+...XX
+....X
+.X...
+.XX..
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/EmptySpacesWithThreeNeighboursCreateACell.story b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/EmptySpacesWithThreeNeighboursCreateACell.story
new file mode 100644
index 0000000..cbc248e
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/EmptySpacesWithThreeNeighboursCreateACell.story
@@ -0,0 +1,42 @@
+Story: Empty spaces with three neighbours create a cell
+
+As a game producer
+I want empty cells with three neighbours to die
+So that I have a minimum feature set to ship
+
+Scenario: the glider
+
+Given the grid looks like
+...X..
+..X...
+..XXX.
+......
+......
+When the next step occurs
+Then the grid should look like
+......
+..X.X.
+..XX..
+...X..
+......
+When the next step occurs
+Then the grid should look like
+......
+..X...
+..X.X.
+..XX..
+......
+When the next step occurs
+Then the grid should look like
+......
+...X..
+.XX...
+..XX..
+......
+When the next step occurs
+Then the grid should look like
+......
+..X...
+.X....
+.XXX..
+......
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/ICanCreateACell.story b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/ICanCreateACell.story
new file mode 100644
index 0000000..88895cb
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/ICanCreateACell.story
@@ -0,0 +1,42 @@
+Story: I can create a cell
+
+As a game producer
+I want to create a cell
+So that I can show the grid to people
+
+Scenario: nothing to see here
+
+Given a 3 x 3 game
+Then the grid should look like
+...
+...
+...
+
+Scenario: all on its lonesome
+
+Given a 3 x 3 game
+When I create a cell at 1, 1
+Then the grid should look like
+...
+.X.
+...
+
+Scenario: the grid has three cells
+
+Given a 3 x 3 game
+When I create a cell at 0, 0
+and I create a cell at 0, 1
+and I create a cell at 2, 2
+Then the grid should look like
+XX.
+...
+..X
+
+Scenario: more cells more more
+
+Given the grid has three cells
+When I create a celll at 3, 1
+Then the grid should look like
+XX.
+..X
+..X
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/ICanKillACell.story b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/ICanKillACell.story
new file mode 100644
index 0000000..a9cf1ac
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/ICanKillACell.story
@@ -0,0 +1,17 @@
+Story: I can kill a cell
+
+As a game producer
+I want to kill a cell
+So that when I make a mistake I dont have to start again
+
+Scenario: bang youre dead
+
+Given the grid looks like
+XX.
+.X.
+..X
+When I destroy the cell at 0, 1
+Then the grid should look like
+X..
+.X.
+..X
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/TheGridWraps.story b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/TheGridWraps.story
new file mode 100644
index 0000000..aeeede7
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/TheGridWraps.story
@@ -0,0 +1,53 @@
+Story: The grid wraps
+
+As a game player
+I want the grid to wrap
+So that untidy stuff at the edges is avoided
+
+Scenario: crowded in the corners
+
+Given the grid looks like
+X.X
+...
+X.X
+When the next step is taken
+Then the grid should look like
+X.X
+...
+X.X
+
+
+Scenario: the glider returns
+
+Given the glider
+......
+..X...
+.X....
+.XXX..
+......
+When the next step is taken
+and the next step is taken
+and the next step is taken
+and the next step is taken
+Then the grid should look like
+......
+......
+.X....
+X.....
+XXX...
+When the next step is taken
+Then the grid should look like
+.X....
+......
+......
+X.X...
+XX....
+When the next step is taken
+Then the grid should look like
+XX....
+......
+......
+X.....
+X.X...
+
+
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/create_a_cell.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/create_a_cell.rb
new file mode 100644
index 0000000..81f86ba
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/create_a_cell.rb
@@ -0,0 +1,52 @@
+require File.join(File.dirname(__FILE__), *%w[helper])
+
+Story "I can create a cell",
+  %(As a game producer
+    I want to create a cell
+    So that I can show the grid to people), :steps_for => :life do
+  
+  Scenario "nothing to see here" do
+    Given "a game with dimensions", 3, 3 do |rows,cols|
+      @game = Game.new(rows,cols)
+    end
+    
+    Then "the grid should look like", %(
+      ...
+      ...
+      ...
+    )
+  end
+  
+  Scenario "all on its lonesome" do
+    Given "a game with dimensions", 2, 2
+    When "I create a cell at", 1, 1 do |row,col|
+      @game.create_at(row,col)
+    end
+    Then "the grid should look like", %(
+      ..
+      .X
+    )
+  end
+  
+  Scenario "the grid has three cells" do
+    Given "a game with dimensions", 3, 3
+    When "I create a cell at", 0, 0
+    When "I create a cell at", 0, 1
+    When "I create a cell at", 2, 2
+    Then "the grid should look like", %(
+      XX.
+      ...
+      ..X
+    )
+  end
+  
+  Scenario "more cells more more" do
+    GivenScenario "the grid has three cells"
+    When "I create a cell at", 2, 0
+    Then "the grid should look like", %(
+      XX.
+      ...
+      X.X
+    )
+  end
+end
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/helper.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/helper.rb
new file mode 100644
index 0000000..70ed21e
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/helper.rb
@@ -0,0 +1,6 @@
+dir = File.dirname(__FILE__)
+$LOAD_PATH.unshift(File.expand_path("#{dir}/../../../../../../rspec/lib"))
+require 'spec'
+$LOAD_PATH.unshift(File.expand_path("#{dir}/../../"))
+require "#{dir}/../../life"
+require File.join(File.dirname(__FILE__), *%w[steps])
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/kill_a_cell.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/kill_a_cell.rb
new file mode 100644
index 0000000..7ae2d91
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/kill_a_cell.rb
@@ -0,0 +1,26 @@
+require File.join(File.dirname(__FILE__), *%w[helper])
+
+Story 'I can kill a cell',
+  %(As a game producer
+  I want to kill a cell
+  So that when I make a mistake I don't have to start again), :steps_for => :life do
+  
+  Scenario "bang, you're dead" do
+    
+    Given 'a game that looks like', %(
+      XX.
+      .X.
+      ..X
+    ) do |dots|
+      @game = Game.from_string dots
+    end
+    When 'I destroy the cell at', 0, 1 do |row,col|
+      @game.destroy_at(row,col)
+    end
+    Then 'the grid should look like', %(
+      X..
+      .X.
+      ..X
+    )
+  end
+end
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/steps.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/steps.rb
new file mode 100644
index 0000000..793590d
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/steps.rb
@@ -0,0 +1,5 @@
+steps_for :life do
+  Then "the grid should look like" do |dots|
+    @game.grid.should == Grid.from_string(dots)
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/stories.rb b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/stories.rb
new file mode 100644
index 0000000..e60fe01
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/stories.rb
@@ -0,0 +1,3 @@
+require File.join(File.dirname(__FILE__), *%w[helper])
+require 'behaviour/stories/create_a_cell'
+require 'behaviour/stories/kill_a_cell'
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/stories.txt b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/stories.txt
new file mode 100644
index 0000000..d8f809b
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/behaviour/stories/stories.txt
@@ -0,0 +1,22 @@
+Story: Show the game field
+    As a game player
+    I want to see the field
+    so that I can observe the progress of the organisms
+
+Scenario: an empty field
+  Given a new game starts
+  When the game displays the field
+  Then the field should be empty
+
+
+
+
+
+StoryBuilder story = stories.createStory().called("a story")
+	.asA("person")
+	.iWant("to do something")
+	.soThat("I can rule the world");
+story.addScenario().called("happy path").as()
+	.given("some context")
+	.when("some event happens")
+	.then("expect some outcome");
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/life.rb b/vendor/gems/rspec/examples/stories/game-of-life/life.rb
new file mode 100644
index 0000000..88263bd
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/life.rb
@@ -0,0 +1,3 @@
+$: << File.dirname(__FILE__)
+require 'life/game'
+require 'life/grid'
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/life/game.rb b/vendor/gems/rspec/examples/stories/game-of-life/life/game.rb
new file mode 100644
index 0000000..5411b01
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/life/game.rb
@@ -0,0 +1,23 @@
+class Game
+  attr_accessor :grid
+  def initialize(rows,cols)
+    @grid = Grid.new(rows, cols)
+  end
+  
+  def create_at(row,col)
+    @grid.create_at(row,col)
+  end
+  
+  def destroy_at(row,col)
+    @grid.destroy_at(row, col)
+  end
+  
+  def self.from_string(dots)
+    grid = Grid.from_string(dots)
+    game = new(grid.rows, grid.columns)
+    game.instance_eval do
+      @grid = grid
+    end
+    return game
+  end
+end
diff --git a/vendor/gems/rspec/examples/stories/game-of-life/life/grid.rb b/vendor/gems/rspec/examples/stories/game-of-life/life/grid.rb
new file mode 100644
index 0000000..aca2308
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/game-of-life/life/grid.rb
@@ -0,0 +1,43 @@
+class Grid
+  
+  attr_accessor :contents
+  
+  def initialize(rows, cols)
+    @contents = []
+    rows.times do @contents << [0] * cols end
+  end
+  
+  def rows
+    @contents.size
+  end
+  
+  def columns
+    @contents[0].size
+  end
+  
+  def ==(other)
+    self.contents == other.contents
+  end
+  
+  def create_at(row,col)
+    @contents[row][col] = 1
+  end
+  
+  def destroy_at(row,col)
+    @contents[row][col] = 0
+  end
+  
+  def self.from_string(str)
+    row_strings = str.split(' ')
+    grid = new(row_strings.size, row_strings[0].size)
+    
+    row_strings.each_with_index do |row, row_index|
+      row_chars = row.split(//)
+      row_chars.each_with_index do |col_char, col_index|
+        grid.create_at(row_index, col_index) if col_char == 'X'
+      end
+    end
+    return grid
+  end
+  
+end
diff --git a/vendor/gems/rspec/examples/stories/helper.rb b/vendor/gems/rspec/examples/stories/helper.rb
new file mode 100644
index 0000000..2e825b2
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/helper.rb
@@ -0,0 +1,9 @@
+$:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
+require 'spec/story'
+
+# won't have to do this once plain_text_story_runner is moved into the library
+# require File.join(File.dirname(__FILE__), "plain_text_story_runner")
+
+Dir[File.join(File.dirname(__FILE__), "steps/*.rb")].each do |file|
+  require file
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/examples/stories/steps/addition_steps.rb b/vendor/gems/rspec/examples/stories/steps/addition_steps.rb
new file mode 100644
index 0000000..3f27095
--- /dev/null
+++ b/vendor/gems/rspec/examples/stories/steps/addition_steps.rb
@@ -0,0 +1,18 @@
+require File.expand_path("#{File.dirname(__FILE__)}/../helper")
+
+# This creates steps for :addition
+steps_for(:addition) do
+  Given("an addend of $addend") do |addend|
+    @adder ||= Adder.new
+    @adder << addend.to_i
+  end
+end
+
+# This appends to them
+steps_for(:addition) do
+  When("the addends are added")  { @sum = @adder.sum }
+end
+
+steps_for(:more_addition) do
+  Then("the sum should be $sum") { |sum| @sum.should == sum.to_i }
+end
diff --git a/vendor/gems/rspec/failing_examples/README.txt b/vendor/gems/rspec/failing_examples/README.txt
new file mode 100644
index 0000000..38c667d
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/README.txt
@@ -0,0 +1,7 @@
+"Why have failing examples?", you might ask.
+
+They allow us to see failure messages. RSpec wants to provide meaningful and helpful failure messages. The failures in this directory not only provide you a way of seeing the failure messages, but they provide RSpec's own specs a way of describing what they should look like and ensuring they stay correct.
+
+To see the types of messages you can expect, stand in this directory and run:
+
+../bin/spec ./*.rb
\ No newline at end of file
diff --git a/vendor/gems/rspec/failing_examples/diffing_spec.rb b/vendor/gems/rspec/failing_examples/diffing_spec.rb
new file mode 100644
index 0000000..85e13e8
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/diffing_spec.rb
@@ -0,0 +1,36 @@
+describe "Running specs with --diff" do
+  it "should print diff of different strings" do
+    uk = <<-EOF
+RSpec is a
+behaviour driven development
+framework for Ruby
+EOF
+    usa = <<-EOF
+RSpec is a
+behavior driven development
+framework for Ruby
+EOF
+    usa.should == uk
+  end
+
+  class Animal
+    def initialize(name,species)
+      @name, at species = name,species
+    end
+
+    def inspect
+      <<-EOA
+<Animal
+name=#{@name},
+species=#{@species}
+>
+      EOA
+    end
+  end
+
+  it "should print diff of different objects' pretty representation" do
+    expected = Animal.new "bob", "giraffe"
+    actual   = Animal.new "bob", "tortoise"
+    expected.should eql(actual)
+  end
+end
diff --git a/vendor/gems/rspec/failing_examples/failing_autogenerated_docstrings_example.rb b/vendor/gems/rspec/failing_examples/failing_autogenerated_docstrings_example.rb
new file mode 100644
index 0000000..8a7d249
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/failing_autogenerated_docstrings_example.rb
@@ -0,0 +1,19 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+# Run spec w/ -fs to see the output of this file
+
+describe "Failing examples with no descriptions" do
+  
+  # description is auto-generated as "should equal(5)" based on the last #should
+  it do
+    3.should equal(2)
+    5.should equal(5)
+  end
+  
+  it { 3.should be > 5 }
+  
+  it { ["a"].should include("b") }
+  
+  it { [1,2,3].should_not respond_to(:size) }
+  
+end
diff --git a/vendor/gems/rspec/failing_examples/failure_in_setup.rb b/vendor/gems/rspec/failing_examples/failure_in_setup.rb
new file mode 100644
index 0000000..2a807a9
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/failure_in_setup.rb
@@ -0,0 +1,10 @@
+describe "This example" do
+  
+  before(:each) do
+    NonExistentClass.new
+  end
+  
+  it "should be listed as failing in setup" do
+  end
+  
+end
diff --git a/vendor/gems/rspec/failing_examples/failure_in_teardown.rb b/vendor/gems/rspec/failing_examples/failure_in_teardown.rb
new file mode 100644
index 0000000..6458ea2
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/failure_in_teardown.rb
@@ -0,0 +1,10 @@
+describe "This example" do
+  
+  it "should be listed as failing in teardown" do
+  end
+  
+  after(:each) do
+    NonExistentClass.new
+  end
+  
+end
diff --git a/vendor/gems/rspec/failing_examples/mocking_example.rb b/vendor/gems/rspec/failing_examples/mocking_example.rb
new file mode 100644
index 0000000..caf2db0
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/mocking_example.rb
@@ -0,0 +1,40 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+describe "Mocker" do
+
+  it "should be able to call mock()" do
+    mock = mock("poke me")
+    mock.should_receive(:poke)
+    mock.poke
+  end
+
+  it "should fail when expected message not received" do
+    mock = mock("poke me")
+    mock.should_receive(:poke)
+  end
+  
+  it "should fail when messages are received out of order" do
+    mock = mock("one two three")
+    mock.should_receive(:one).ordered
+    mock.should_receive(:two).ordered
+    mock.should_receive(:three).ordered
+    mock.one
+    mock.three
+    mock.two
+  end
+
+  it "should get yelled at when sending unexpected messages" do
+    mock = mock("don't talk to me")
+    mock.should_not_receive(:any_message_at_all)
+    mock.any_message_at_all
+  end
+
+  it "has a bug we need to fix" do
+    pending "here is the bug" do
+      # Actually, no. It's fixed. This will fail because it passes :-)
+      mock = mock("Bug")
+      mock.should_receive(:hello)
+      mock.hello
+    end
+  end
+end
diff --git a/vendor/gems/rspec/failing_examples/mocking_with_flexmock.rb b/vendor/gems/rspec/failing_examples/mocking_with_flexmock.rb
new file mode 100644
index 0000000..6e79ece
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/mocking_with_flexmock.rb
@@ -0,0 +1,26 @@
+# stub frameworks like to gum up Object, so this is deliberately
+# set NOT to run so that you don't accidentally run it when you
+# run this dir.
+
+# To run it, stand in this directory and say:
+#
+#   RUN_FLEXMOCK_EXAMPLE=true ruby ../bin/spec mocking_with_flexmock.rb
+
+if ENV['RUN_FLEXMOCK_EXAMPLE']
+  Spec::Runner.configure do |config|
+    config.mock_with :flexmock
+  end
+
+  describe "Flexmocks" do
+    it "should fail when the expected message is received with wrong arguments" do
+      m = flexmock("now flex!")
+      m.should_receive(:msg).with("arg").once
+      m.msg("other arg")
+    end
+
+    it "should fail when the expected message is not received at all" do
+      m = flexmock("now flex!")
+      m.should_receive(:msg).with("arg").once
+    end
+  end
+end
diff --git a/vendor/gems/rspec/failing_examples/mocking_with_mocha.rb b/vendor/gems/rspec/failing_examples/mocking_with_mocha.rb
new file mode 100644
index 0000000..f14a1a3
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/mocking_with_mocha.rb
@@ -0,0 +1,25 @@
+# stub frameworks like to gum up Object, so this is deliberately
+# set NOT to run so that you don't accidentally run it when you
+# run this dir.
+
+# To run it, stand in this directory and say:
+#
+#   RUN_MOCHA_EXAMPLE=true ruby ../bin/spec mocking_with_mocha.rb
+
+if ENV['RUN_MOCHA_EXAMPLE']
+  Spec::Runner.configure do |config|
+    config.mock_with :mocha
+  end
+  describe "Mocha framework" do
+    it "should should be made available by saying config.mock_with :mocha" do
+      m = mock()
+      m.expects(:msg).with("arg")
+      m.msg
+    end
+    it "should should be made available by saying config.mock_with :mocha" do
+      o = Object.new
+      o.expects(:msg).with("arg")
+      o.msg
+    end
+  end
+end
diff --git a/vendor/gems/rspec/failing_examples/mocking_with_rr.rb b/vendor/gems/rspec/failing_examples/mocking_with_rr.rb
new file mode 100644
index 0000000..0d2b4fe
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/mocking_with_rr.rb
@@ -0,0 +1,27 @@
+# stub frameworks like to gum up Object, so this is deliberately
+# set NOT to run so that you don't accidentally run it when you
+# run this dir.
+
+# To run it, stand in this directory and say:
+#
+#   RUN_RR_EXAMPLE=true ruby ../bin/spec mocking_with_rr.rb
+
+if ENV['RUN_RR_EXAMPLE']
+  Spec::Runner.configure do |config|
+    config.mock_with :rr
+  end
+  describe "RR framework" do
+    it "should should be made available by saying config.mock_with :rr" do
+      o = Object.new
+      mock(o).msg("arg")
+      o.msg
+    end
+    it "should should be made available by saying config.mock_with :rr" do
+      o = Object.new
+      mock(o) do |m|
+        m.msg("arg")
+      end
+      o.msg
+    end
+  end
+end
diff --git a/vendor/gems/rspec/failing_examples/partial_mock_example.rb b/vendor/gems/rspec/failing_examples/partial_mock_example.rb
new file mode 100644
index 0000000..6d05540
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/partial_mock_example.rb
@@ -0,0 +1,20 @@
+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 (but fail here due to the type mismatch)" 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
+
+end
diff --git a/vendor/gems/rspec/failing_examples/predicate_example.rb b/vendor/gems/rspec/failing_examples/predicate_example.rb
new file mode 100644
index 0000000..53b6367
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/predicate_example.rb
@@ -0,0 +1,29 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+class BddFramework
+  def intuitive?
+    true
+  end
+
+  def adopted_quickly?
+    #this will cause failures because it reallly SHOULD be adopted quickly
+    false
+  end
+end
+
+describe "BDD framework" do
+
+  before(:each) do
+    @bdd_framework = BddFramework.new
+  end
+
+  it "should be adopted quickly" do
+    #this will fail because it reallly SHOULD be adopted quickly
+    @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/failing_examples/raising_example.rb b/vendor/gems/rspec/failing_examples/raising_example.rb
new file mode 100644
index 0000000..e40b51e
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/raising_example.rb
@@ -0,0 +1,47 @@
+describe "This example" do
+  
+  it "should show that a NoMethodError is raised but an Exception was expected" do
+    proc { ''.nonexistent_method }.should raise_error
+  end
+  
+  it "should pass" do
+    proc { ''.nonexistent_method }.should raise_error(NoMethodError)
+  end
+  
+  it "should show that a NoMethodError is raised but a SyntaxError was expected" do
+    proc { ''.nonexistent_method }.should raise_error(SyntaxError)
+  end
+  
+  it "should show that nothing is raised when SyntaxError was expected" do
+    proc { }.should raise_error(SyntaxError)
+  end
+
+  it "should show that a NoMethodError is raised but a Exception was expected" do
+    proc { ''.nonexistent_method }.should_not raise_error
+  end
+  
+  it "should show that a NoMethodError is raised" do
+    proc { ''.nonexistent_method }.should_not raise_error(NoMethodError)
+  end
+  
+  it "should also pass" do
+    proc { ''.nonexistent_method }.should_not raise_error(SyntaxError)
+  end
+  
+  it "should show that a NoMethodError is raised when nothing expected" do
+    proc { ''.nonexistent_method }.should_not raise_error(Exception)
+  end
+  
+  it "should show that the wrong message was received" do
+    proc { raise StandardError.new("what is an enterprise?") }.should raise_error(StandardError, "not this")
+  end
+  
+  it "should show that the unexpected error/message was thrown" do
+    proc { raise StandardError.new("abc") }.should_not raise_error(StandardError, "abc")
+  end
+  
+  it "should pass too" do
+    proc { raise StandardError.new("abc") }.should_not raise_error(StandardError, "xyz")
+  end
+  
+end
diff --git a/vendor/gems/rspec/failing_examples/spec_helper.rb b/vendor/gems/rspec/failing_examples/spec_helper.rb
new file mode 100644
index 0000000..f8d6575
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/spec_helper.rb
@@ -0,0 +1,3 @@
+lib_path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
+$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
+require "spec"
diff --git a/vendor/gems/rspec/failing_examples/syntax_error_example.rb b/vendor/gems/rspec/failing_examples/syntax_error_example.rb
new file mode 100644
index 0000000..c9bb907
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/syntax_error_example.rb
@@ -0,0 +1,7 @@
+describe "when passing a block to a matcher" do
+  it "you should use {} instead of do/end" do
+    Object.new.should satisfy do
+      "this block is being passed to #should instead of #satisfy - use {} instead"
+    end
+  end
+end
diff --git a/vendor/gems/rspec/failing_examples/team_spec.rb b/vendor/gems/rspec/failing_examples/team_spec.rb
new file mode 100644
index 0000000..41a44e5
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/team_spec.rb
@@ -0,0 +1,44 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+
+class Team
+  attr_reader :players
+  def initialize
+    @players = Players.new
+  end
+end
+
+class Players
+  def initialize
+    @players = []
+  end
+  def size
+    @players.size
+  end
+  def include? player
+    raise "player must be a string" unless player.is_a?(String)
+    @players.include? player
+  end
+end
+
+describe "A new team" do
+  
+  before(:each) do
+    @team = Team.new
+  end
+  
+  it "should have 3 players (failing example)" do
+    @team.should have(3).players
+  end
+  
+  it "should include some player (failing example)" do
+    @team.players.should include("Some Player")
+  end
+
+  it "should include 5 (failing example)" do
+    @team.players.should include(5)
+  end
+  
+  it "should have no players"
+  
+end
diff --git a/vendor/gems/rspec/failing_examples/timeout_behaviour.rb b/vendor/gems/rspec/failing_examples/timeout_behaviour.rb
new file mode 100644
index 0000000..1822136
--- /dev/null
+++ b/vendor/gems/rspec/failing_examples/timeout_behaviour.rb
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+describe "Something really slow" do
+  it "should be failed by RSpec when it takes longer than --timeout" do
+    sleep(2)
+  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 0000000..81914c3
--- /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 0000000..9c97d2e
--- /dev/null
+++ b/vendor/gems/rspec/lib/autotest/rspec.rb
@@ -0,0 +1,74 @@
+require 'autotest'
+
+Autotest.add_hook :initialize do |at|
+  at.clear_mappings
+  # watch out: Ruby bug (1.8.6):
+  # %r(/) != /\//
+  at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _| 
+    filename 
+  }
+  at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| 
+    ["spec/#{m[1]}_spec.rb"]
+  }
+  at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) { 
+    at.files_matching %r%^spec/.*_spec\.rb$%
+  }
+end
+
+class RspecCommandError < StandardError; end
+
+class Autotest::Rspec < Autotest
+
+  def initialize
+    super
+
+    self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m
+    self.completed_re = /\Z/ # FIX: some sort of summary line at the end?
+  end
+
+  def consolidate_failures(failed)
+    filters = Hash.new { |h,k| h[k] = [] }
+    failed.each do |spec, failed_trace|
+      if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } then
+        filters[f] << spec
+        break
+      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(separator=File::ALT_SEPARATOR)
+    unless defined? @spec_command then
+      @spec_command = spec_commands.find { |cmd| File.exists? cmd }
+
+      raise RspecCommandError, "No spec command could be found!" unless @spec_command
+
+      @spec_command.gsub! File::SEPARATOR, separator if separator
+    end
+    @spec_command
+  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.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')),
+      File.join(Config::CONFIG['bindir'], 'spec')
+    ]
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec.rb b/vendor/gems/rspec/lib/spec.rb
new file mode 100644
index 0000000..c143aa8
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec.rb
@@ -0,0 +1,30 @@
+require 'spec/version'
+require 'spec/matchers'
+require 'spec/expectations'
+require 'spec/example'
+require 'spec/extensions'
+require 'spec/runner'
+
+if Object.const_defined?(:Test); \
+  require 'spec/interop/test'; \
+end
+
+module Spec
+  class << self
+    def run?
+      @run || rspec_options.examples_run?
+    end
+
+    def run; \
+      return true if run?; \
+      result = rspec_options.run_examples; \
+      @run = true; \
+      result; \
+    end
+    attr_writer :run
+    
+    def exit?; \
+      !Object.const_defined?(:Test) || Test::Unit.run?; \
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/example.rb b/vendor/gems/rspec/lib/spec/example.rb
new file mode 100644
index 0000000..39ff76b
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example.rb
@@ -0,0 +1,12 @@
+require 'timeout'
+require 'forwardable'
+require 'spec/example/pending'
+require 'spec/example/module_reopening_fix'
+require 'spec/example/example_group_methods'
+require 'spec/example/example_methods'
+require 'spec/example/example_group'
+require 'spec/example/shared_example_group'
+require 'spec/example/example_group_factory'
+require 'spec/example/errors'
+require 'spec/example/configuration'
+require 'spec/example/example_matcher'
diff --git a/vendor/gems/rspec/lib/spec/example/configuration.rb b/vendor/gems/rspec/lib/spec/example/configuration.rb
new file mode 100755
index 0000000..6741847
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/configuration.rb
@@ -0,0 +1,144 @@
+module Spec
+  module Example
+    class Configuration
+      # Chooses what mock framework to use. Example:
+      #
+      #   Spec::Runner.configure do |config|
+      #     config.mock_with :rspec, :mocha, :flexmock, or :rr
+      #   end
+      #
+      # To use any other mock framework, you'll have to provide
+      # your own adapter. This is simply a module that responds to
+      # setup_mocks_for_rspec, verify_mocks_for_rspec and teardown_mocks_for_rspec.
+      # These are your hooks into the lifecycle of a given example. RSpec will
+      # call setup_mocks_for_rspec before running anything else in each Example.
+      # After executing the #after methods, RSpec will then call verify_mocks_for_rspec
+      # and teardown_mocks_for_rspec (this is guaranteed to run even if there are
+      # failures in verify_mocks_for_rspec).
+      #
+      # Once you've defined this module, you can pass that to mock_with:
+      #
+      #   Spec::Runner.configure do |config|
+      #     config.mock_with MyMockFrameworkAdapter
+      #   end
+      #
+      def mock_with(mock_framework)
+        @mock_framework = case mock_framework
+        when Symbol
+          mock_framework_path(mock_framework.to_s)
+        else
+          mock_framework
+        end
+      end
+      
+      def mock_framework # :nodoc:
+        @mock_framework ||= mock_framework_path("rspec")
+      end
+      
+      # Declares modules to be included in all example groups (<tt>describe</tt> blocks).
+      #
+      #   config.include(My::Bottle, My::Cup)
+      #
+      # If you want to restrict the inclusion to a subset of all the example groups then
+      # specify this in a Hash as the last argument:
+      #
+      #   config.include(My::Pony, My::Horse, :type => :farm)
+      #
+      # Only example groups that have that type will get the modules included:
+      #
+      #   describe "Downtown", :type => :city do
+      #     # Will *not* get My::Pony and My::Horse included
+      #   end
+      #
+      #   describe "Old Mac Donald", :type => :farm do
+      #     # *Will* get My::Pony and My::Horse included
+      #   end
+      #
+      def include(*args)
+        args << {} unless Hash === args.last
+        modules, options = args_and_options(*args)
+        required_example_group = get_type_from_options(options)
+        required_example_group = required_example_group.to_sym if required_example_group
+        modules.each do |mod|
+          ExampleGroupFactory.get(required_example_group).send(:include, mod)
+        end
+      end
+
+      # Defines global predicate matchers. Example:
+      #
+      #   config.predicate_matchers[:swim] = :can_swim?
+      #
+      # This makes it possible to say:
+      #
+      #   person.should swim # passes if person.should_swim? returns true
+      #
+      def predicate_matchers
+        @predicate_matchers ||= {}
+      end
+      
+      # Prepends a global <tt>before</tt> block to all example groups.
+      # See #append_before for filtering semantics.
+      def prepend_before(*args, &proc)
+        scope, options = scope_and_options(*args)
+        example_group = ExampleGroupFactory.get(
+          get_type_from_options(options)
+        )
+        example_group.prepend_before(scope, &proc)
+      end
+      # Appends a global <tt>before</tt> block to all example groups.
+      #
+      # If you want to restrict the block to a subset of all the example groups then
+      # specify this in a Hash as the last argument:
+      #
+      #   config.prepend_before(:all, :type => :farm)
+      #
+      # or
+      #
+      #   config.prepend_before(:type => :farm)
+      #
+      def append_before(*args, &proc)
+        scope, options = scope_and_options(*args)
+        example_group = ExampleGroupFactory.get(
+          get_type_from_options(options)
+        )
+        example_group.append_before(scope, &proc)
+      end
+      alias_method :before, :append_before
+
+      # Prepends a global <tt>after</tt> block to all example groups.
+      # See #append_before for filtering semantics.
+      def prepend_after(*args, &proc)
+        scope, options = scope_and_options(*args)
+        example_group = ExampleGroupFactory.get(
+          get_type_from_options(options)
+        )
+        example_group.prepend_after(scope, &proc)
+      end
+      alias_method :after, :prepend_after
+      # Appends a global <tt>after</tt> block to all example groups.
+      # See #append_before for filtering semantics.
+      def append_after(*args, &proc)
+        scope, options = scope_and_options(*args)
+        example_group = ExampleGroupFactory.get(
+          get_type_from_options(options)
+        )
+        example_group.append_after(scope, &proc)
+      end
+
+    private
+
+      def scope_and_options(*args)
+        args, options = args_and_options(*args)
+        scope = (args[0] || :each), options
+      end
+
+      def get_type_from_options(options)
+        options[:type] || options[:behaviour_type]
+      end
+    
+      def mock_framework_path(framework_name)
+        File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "plugins", "mock_frameworks", framework_name))
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/example/errors.rb b/vendor/gems/rspec/lib/spec/example/errors.rb
new file mode 100644
index 0000000..c6cb224
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/errors.rb
@@ -0,0 +1,9 @@
+module Spec
+  module Example
+    class ExamplePendingError < StandardError
+    end
+
+    class PendingExampleFixedError < StandardError
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/example/example_group.rb b/vendor/gems/rspec/lib/spec/example/example_group.rb
new file mode 100644
index 0000000..d6e156f
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/example_group.rb
@@ -0,0 +1,16 @@
+module Spec
+  module Example
+    # The superclass for all regular RSpec examples.
+    class ExampleGroup
+      extend Spec::Example::ExampleGroupMethods
+      include Spec::Example::ExampleMethods
+
+      def initialize(defined_description, &implementation)
+        @_defined_description = defined_description
+        @_implementation = implementation
+      end
+    end
+  end
+end
+
+Spec::ExampleGroup = Spec::Example::ExampleGroup
diff --git a/vendor/gems/rspec/lib/spec/example/example_group_factory.rb b/vendor/gems/rspec/lib/spec/example/example_group_factory.rb
new file mode 100755
index 0000000..0414a3b
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/example_group_factory.rb
@@ -0,0 +1,62 @@
+module Spec
+  module Example
+    class ExampleGroupFactory
+      class << self
+        def reset
+          @example_group_types = nil
+          default(ExampleGroup)
+        end
+
+        # Registers an example group class +klass+ with the symbol
+        # +type+. For example:
+        #
+        #   Spec::Example::ExampleGroupFactory.register(:farm, Spec::Farm::Example::FarmExampleGroup)
+        #
+        # This will cause Main#describe from a file living in 
+        # <tt>spec/farm</tt> to create example group instances of type
+        # Spec::Farm::Example::FarmExampleGroup.
+        def register(id, example_group_class)
+          @example_group_types[id] = example_group_class
+        end
+        
+        # Sets the default ExampleGroup class
+        def default(example_group_class)
+          old = @example_group_types
+          @example_group_types = Hash.new(example_group_class)
+          @example_group_types.merge(old) if old
+        end
+
+        def get(id=nil)
+          if @example_group_types.values.include?(id)
+            id
+          else
+            @example_group_types[id]
+          end
+        end
+        
+        def create_example_group(*args, &block)
+          opts = Hash === args.last ? args.last : {}
+          if opts[:shared]
+            SharedExampleGroup.new(*args, &block)
+          else
+            superclass = determine_superclass(opts)
+            superclass.describe(*args, &block)
+          end
+        end
+
+        protected
+
+        def determine_superclass(opts)
+          id = if opts[:type]
+            opts[:type]
+          elsif opts[:spec_path] =~ /spec(\\|\/)(#{@example_group_types.keys.join('|')})/
+            $2 == '' ? nil : $2.to_sym
+          end
+          get(id)
+        end
+
+      end
+      self.reset
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/example/example_group_methods.rb b/vendor/gems/rspec/lib/spec/example/example_group_methods.rb
new file mode 100644
index 0000000..a348bc7
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/example_group_methods.rb
@@ -0,0 +1,424 @@
+module Spec
+  module Example
+
+    module ExampleGroupMethods
+      class << self
+        def description_text(*args)
+          args.inject("") do |result, arg|
+            result << " " unless (result == "" || arg.to_s =~ /^(\s|\.|#)/)
+            result << arg.to_s
+          end
+        end
+      end
+
+      attr_reader :description_text, :description_args, :description_options, :spec_path, :registration_binding_block
+
+      def inherited(klass)
+        super
+        klass.register {}
+        Spec::Runner.register_at_exit_hook
+      end
+      
+      # Makes the describe/it syntax available from a class. For example:
+      #
+      #   class StackSpec < Spec::ExampleGroup
+      #     describe Stack, "with no elements"
+      #
+      #     before
+      #       @stack = Stack.new
+      #     end
+      #
+      #     it "should raise on pop" do
+      #       lambda{ @stack.pop }.should raise_error
+      #     end
+      #   end
+      #
+      def describe(*args, &example_group_block)
+        if example_group_block
+          self.subclass("Subclass") do
+            describe(*args)
+            module_eval(&example_group_block)
+          end
+        else
+          set_description(*args)
+          before_eval
+          self
+        end
+      end
+
+      # Use this to pull in examples from shared example groups.
+      # See Spec::Runner for information about shared example groups.
+      def it_should_behave_like(shared_example_group)
+        case shared_example_group
+        when SharedExampleGroup
+          include shared_example_group
+        else
+          example_group = SharedExampleGroup.find_shared_example_group(shared_example_group)
+          unless example_group
+            raise RuntimeError.new("Shared Example Group '#{shared_example_group}' can not be found")
+          end
+          include(example_group)
+        end
+      end
+
+      # :call-seq:
+      #   predicate_matchers[matcher_name] = method_on_object
+      #   predicate_matchers[matcher_name] = [method1_on_object, method2_on_object]
+      #
+      # Dynamically generates a custom matcher that will match
+      # a predicate on your class. RSpec provides a couple of these
+      # out of the box:
+      #
+      #   exist (or state expectations)
+      #     File.should exist("path/to/file")
+      #
+      #   an_instance_of (for mock argument constraints)
+      #     mock.should_receive(:message).with(an_instance_of(String))
+      #
+      # == Examples
+      #
+      #   class Fish
+      #     def can_swim?
+      #       true
+      #     end
+      #   end
+      #
+      #   describe Fish do
+      #     predicate_matchers[:swim] = :can_swim?
+      #     it "should swim" do
+      #       Fish.new.should swim
+      #     end
+      #   end
+      def predicate_matchers
+        @predicate_matchers ||= {:an_instance_of => :is_a?}
+      end
+
+      # Creates an instance of Spec::Example::Example and adds
+      # it to a collection of examples of the current example group.
+      def it(description=nil, &implementation)
+        e = new(description, &implementation)
+        example_objects << e
+        e
+      end
+
+      alias_method :specify, :it
+
+      # Use this to temporarily disable an example.
+      def xit(description=nil, opts={}, &block)
+        Kernel.warn("Example disabled: #{description}")
+      end
+
+      def run
+        examples = examples_to_run
+        return true if examples.empty?
+        reporter.add_example_group(self)
+        return dry_run(examples) if dry_run?
+
+        plugin_mock_framework
+        define_methods_from_predicate_matchers
+
+        success, before_all_instance_variables = run_before_all
+        success, after_all_instance_variables  = execute_examples(success, before_all_instance_variables, examples)
+        success                                = run_after_all(success, after_all_instance_variables)
+      end
+
+      def description
+        result = ExampleGroupMethods.description_text(*description_parts)
+        if result.nil? || result == ""
+          return to_s
+        else
+          result
+        end
+      end
+
+      def described_type
+        description_parts.find {|part| part.is_a?(Module)}
+      end
+
+      def description_parts #:nodoc:
+        parts = []
+        execute_in_class_hierarchy do |example_group|
+          parts << example_group.description_args
+        end
+        parts.flatten.compact
+      end
+
+      def set_description(*args)
+        args, options = args_and_options(*args)
+        @description_args = args
+        @description_options = options
+        @description_text = ExampleGroupMethods.description_text(*args)
+        @spec_path = File.expand_path(options[:spec_path]) if options[:spec_path]
+        if described_type.class == Module
+          include described_type
+        end
+        self
+      end
+
+      def examples #:nodoc:
+        examples = example_objects.dup
+        add_method_examples(examples)
+        rspec_options.reverse ? examples.reverse : examples
+      end
+
+      def number_of_examples #:nodoc:
+        examples.length
+      end
+
+      # Registers a block to be executed before each example.
+      # This method prepends +block+ to existing before blocks.
+      def prepend_before(*args, &block)
+        scope, options = scope_and_options(*args)
+        parts = before_parts_from_scope(scope)
+        parts.unshift(block)
+      end
+
+      # Registers a block to be executed before each example.
+      # This method appends +block+ to existing before blocks.
+      def append_before(*args, &block)
+        scope, options = scope_and_options(*args)
+        parts = before_parts_from_scope(scope)
+        parts << block
+      end
+      alias_method :before, :append_before
+
+      # Registers a block to be executed after each example.
+      # This method prepends +block+ to existing after blocks.
+      def prepend_after(*args, &block)
+        scope, options = scope_and_options(*args)
+        parts = after_parts_from_scope(scope)
+        parts.unshift(block)
+      end
+      alias_method :after, :prepend_after
+
+      # Registers a block to be executed after each example.
+      # This method appends +block+ to existing after blocks.
+      def append_after(*args, &block)
+        scope, options = scope_and_options(*args)
+        parts = after_parts_from_scope(scope)
+        parts << block
+      end
+
+      def remove_after(scope, &block)
+        after_each_parts.delete(block)
+      end
+
+      # Deprecated. Use before(:each)
+      def setup(&block)
+        before(:each, &block)
+      end
+
+      # Deprecated. Use after(:each)
+      def teardown(&block)
+        after(:each, &block)
+      end
+
+      def before_all_parts # :nodoc:
+        @before_all_parts ||= []
+      end
+
+      def after_all_parts # :nodoc:
+        @after_all_parts ||= []
+      end
+
+      def before_each_parts # :nodoc:
+        @before_each_parts ||= []
+      end
+
+      def after_each_parts # :nodoc:
+        @after_each_parts ||= []
+      end
+
+      # Only used from RSpec's own examples
+      def reset # :nodoc:
+        @before_all_parts = nil
+        @after_all_parts = nil
+        @before_each_parts = nil
+        @after_each_parts = nil
+      end
+
+      def register(&registration_binding_block)
+        @registration_binding_block = registration_binding_block
+        rspec_options.add_example_group self
+      end
+
+      def unregister #:nodoc:
+        rspec_options.remove_example_group self
+      end
+
+      def registration_backtrace
+        eval("caller", registration_binding_block.binding)
+      end
+
+      def run_before_each(example)
+        execute_in_class_hierarchy do |example_group|
+          example.eval_each_fail_fast(example_group.before_each_parts)
+        end
+      end
+
+      def run_after_each(example)
+        execute_in_class_hierarchy(:superclass_first) do |example_group|
+          example.eval_each_fail_slow(example_group.after_each_parts)
+        end
+      end
+
+    private
+      def dry_run(examples)
+        examples.each do |example|
+          rspec_options.reporter.example_started(example)
+          rspec_options.reporter.example_finished(example)
+        end
+        return true
+      end
+
+      def run_before_all
+        before_all = new("before(:all)")
+        begin
+          execute_in_class_hierarchy do |example_group|
+            before_all.eval_each_fail_fast(example_group.before_all_parts)
+          end
+          return [true, before_all.instance_variable_hash]
+        rescue Exception => e
+          reporter.failure(before_all, e)
+          return [false, before_all.instance_variable_hash]
+        end
+      end
+
+      def execute_examples(success, instance_variables, examples)
+        return [success, instance_variables] unless success
+
+        after_all_instance_variables = instance_variables
+        examples.each do |example_group_instance|
+          success &= example_group_instance.execute(rspec_options, instance_variables)
+          after_all_instance_variables = example_group_instance.instance_variable_hash
+        end
+        return [success, after_all_instance_variables]
+      end
+
+      def run_after_all(success, instance_variables)
+        after_all = new("after(:all)")
+        after_all.set_instance_variables_from_hash(instance_variables)
+        execute_in_class_hierarchy(:superclass_first) do |example_group|
+          after_all.eval_each_fail_slow(example_group.after_all_parts)
+        end
+        return success
+      rescue Exception => e
+        reporter.failure(after_all, e)
+        return false
+      end
+
+      def examples_to_run
+        all_examples = examples
+        return all_examples unless specified_examples?
+        all_examples.reject do |example|
+          matcher = ExampleMatcher.new(description.to_s, example.description)
+          !matcher.matches?(specified_examples)
+        end
+      end
+
+      def specified_examples?
+        specified_examples && !specified_examples.empty?
+      end
+
+      def specified_examples
+        rspec_options.examples
+      end
+
+      def reporter
+        rspec_options.reporter
+      end
+
+      def dry_run?
+        rspec_options.dry_run
+      end
+
+      def example_objects
+        @example_objects ||= []
+      end
+
+      def execute_in_class_hierarchy(superclass_last=false)
+        classes = []
+        current_class = self
+        while is_example_group?(current_class)
+          superclass_last ? classes << current_class : classes.unshift(current_class)
+          current_class = current_class.superclass
+        end
+        superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods)
+
+        classes.each do |example_group|
+          yield example_group
+        end
+      end
+
+      def is_example_group?(klass)
+        Module === klass && klass.kind_of?(ExampleGroupMethods)
+      end
+
+      def plugin_mock_framework
+        case mock_framework = Spec::Runner.configuration.mock_framework
+        when Module
+          include mock_framework
+        else
+          require Spec::Runner.configuration.mock_framework
+          include Spec::Plugins::MockFramework
+        end
+      end
+
+      def define_methods_from_predicate_matchers # :nodoc:
+        all_predicate_matchers = predicate_matchers.merge(
+          Spec::Runner.configuration.predicate_matchers
+        )
+        all_predicate_matchers.each_pair do |matcher_method, method_on_object|
+          define_method matcher_method do |*args|
+            eval("be_#{method_on_object.to_s.gsub('?','')}(*args)")
+          end
+        end
+      end
+
+      def scope_and_options(*args)
+        args, options = args_and_options(*args)
+        scope = (args[0] || :each), options
+      end
+
+      def before_parts_from_scope(scope)
+        case scope
+        when :each; before_each_parts
+        when :all; before_all_parts
+        end
+      end
+
+      def after_parts_from_scope(scope)
+        case scope
+        when :each; after_each_parts
+        when :all; after_all_parts
+        end
+      end
+
+      def before_eval
+      end
+
+      def add_method_examples(examples)
+        instance_methods.sort.each do |method_name|
+          if example_method?(method_name)
+            examples << new(method_name) do
+              __send__(method_name)
+            end
+          end
+        end
+      end
+
+      def example_method?(method_name)
+        should_method?(method_name)
+      end
+
+      def should_method?(method_name)
+        !(method_name =~ /^should(_not)?$/) &&
+        method_name =~ /^should/ && (
+          instance_method(method_name).arity == 0 ||
+          instance_method(method_name).arity == -1
+        )
+      end
+    end
+
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/example/example_matcher.rb b/vendor/gems/rspec/lib/spec/example/example_matcher.rb
new file mode 100755
index 0000000..435eabf
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/example_matcher.rb
@@ -0,0 +1,42 @@
+module Spec
+  module Example
+    class ExampleMatcher
+      def initialize(example_group_description, example_name)
+        @example_group_description = example_group_description
+        @example_name = example_name
+      end
+      
+      def matches?(specified_examples)
+        specified_examples.each do |specified_example|
+          return true if matches_literal_example?(specified_example) || matches_example_not_considering_modules?(specified_example)
+        end
+        false
+      end
+      
+      protected
+      def matches_literal_example?(specified_example)
+        specified_example =~ /(^#{example_group_regex} #{example_regexp}$|^#{example_group_regex}$|^#{example_group_with_before_all_regexp}$|^#{example_regexp}$)/
+      end
+
+      def matches_example_not_considering_modules?(specified_example)
+        specified_example =~ /(^#{example_group_regex_not_considering_modules} #{example_regexp}$|^#{example_group_regex_not_considering_modules}$|^#{example_regexp}$)/
+      end
+
+      def example_group_regex
+        Regexp.escape(@example_group_description)
+      end
+
+      def example_group_with_before_all_regexp
+        Regexp.escape("#{@example_group_description} before(:all)")
+      end
+
+      def example_group_regex_not_considering_modules
+        Regexp.escape(@example_group_description.split('::').last)
+      end
+
+      def example_regexp
+        Regexp.escape(@example_name)
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/example/example_methods.rb b/vendor/gems/rspec/lib/spec/example/example_methods.rb
new file mode 100644
index 0000000..babd31d
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/example_methods.rb
@@ -0,0 +1,106 @@
+module Spec
+  module Example
+    module ExampleMethods
+      extend ExampleGroupMethods
+      extend ModuleReopeningFix
+
+      PENDING_EXAMPLE_BLOCK = lambda {
+        raise Spec::Example::ExamplePendingError.new("Not Yet Implemented")
+      }
+
+      def execute(options, instance_variables)
+        options.reporter.example_started(self)
+        set_instance_variables_from_hash(instance_variables)
+        
+        execution_error = nil
+        Timeout.timeout(options.timeout) do
+          begin
+            before_example
+            run_with_description_capturing
+          rescue Exception => e
+            execution_error ||= e
+          end
+          begin
+            after_example
+          rescue Exception => e
+            execution_error ||= e
+          end
+        end
+
+        options.reporter.example_finished(self, execution_error)
+        success = execution_error.nil? || ExamplePendingError === execution_error
+      end
+
+      def instance_variable_hash
+        instance_variables.inject({}) do |variable_hash, variable_name|
+          variable_hash[variable_name] = instance_variable_get(variable_name)
+          variable_hash
+        end
+      end
+
+      def violated(message="")
+        raise Spec::Expectations::ExpectationNotMetError.new(message)
+      end
+
+      def eval_each_fail_fast(procs) #:nodoc:
+        procs.each do |proc|
+          instance_eval(&proc)
+        end
+      end
+
+      def eval_each_fail_slow(procs) #:nodoc:
+        first_exception = nil
+        procs.each do |proc|
+          begin
+            instance_eval(&proc)
+          rescue Exception => e
+            first_exception ||= e
+          end
+        end
+        raise first_exception if first_exception
+      end
+
+      def description
+        @_defined_description || @_matcher_description || "NO NAME"
+      end
+      
+      def set_instance_variables_from_hash(ivars)
+        ivars.each do |variable_name, value|
+          # Ruby 1.9 requires variable.to_s on the next line
+          unless ['@_implementation', '@_defined_description', '@_matcher_description', '@method_name'].include?(variable_name.to_s)
+            instance_variable_set variable_name, value
+          end
+        end
+      end
+
+      def run_with_description_capturing
+        begin
+          return instance_eval(&(@_implementation || PENDING_EXAMPLE_BLOCK))
+        ensure
+          @_matcher_description = Spec::Matchers.generated_description
+          Spec::Matchers.clear_generated_description
+        end
+      end
+
+      def implementation_backtrace
+        eval("caller", @_implementation)
+      end
+      
+      protected
+      include Matchers
+      include Pending
+      
+      def before_example
+        setup_mocks_for_rspec
+        self.class.run_before_each(self)
+      end
+
+      def after_example
+        self.class.run_after_each(self)
+        verify_mocks_for_rspec
+      ensure
+        teardown_mocks_for_rspec
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/example/module_reopening_fix.rb b/vendor/gems/rspec/lib/spec/example/module_reopening_fix.rb
new file mode 100644
index 0000000..dc01dd6
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/module_reopening_fix.rb
@@ -0,0 +1,21 @@
+module Spec
+  module Example
+    # This is a fix for ...Something in Ruby 1.8.6??... (Someone fill in here please - Aslak)
+    module ModuleReopeningFix
+      def child_modules
+        @child_modules ||= []
+      end
+
+      def included(mod)
+        child_modules << mod
+      end
+
+      def include(mod)
+        super
+        child_modules.each do |child_module|
+          child_module.__send__(:include, mod)
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/example/pending.rb b/vendor/gems/rspec/lib/spec/example/pending.rb
new file mode 100644
index 0000000..b1f27c8
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/pending.rb
@@ -0,0 +1,18 @@
+module Spec
+  module Example      
+    module Pending
+      def pending(message = "TODO")
+        if block_given?
+          begin
+            yield
+          rescue Exception => e
+            raise Spec::Example::ExamplePendingError.new(message)
+          end
+          raise Spec::Example::PendingExampleFixedError.new("Expected pending '#{message}' to fail. No Error was raised.")
+        else
+          raise Spec::Example::ExamplePendingError.new(message)
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/example/shared_example_group.rb b/vendor/gems/rspec/lib/spec/example/shared_example_group.rb
new file mode 100644
index 0000000..a6fd621
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/example/shared_example_group.rb
@@ -0,0 +1,58 @@
+module Spec
+  module Example
+    class SharedExampleGroup < Module
+      class << self
+        def add_shared_example_group(new_example_group)
+          guard_against_redefining_existing_example_group(new_example_group)
+          shared_example_groups << new_example_group
+        end
+
+        def find_shared_example_group(example_group_description)
+          shared_example_groups.find do |b|
+            b.description == example_group_description
+          end
+        end
+
+        def shared_example_groups
+          # TODO - this needs to be global, or at least accessible from
+          # from subclasses of Example in a centralized place. I'm not loving
+          # this as a solution, but it works for now.
+          $shared_example_groups ||= []
+        end
+
+        private
+        def guard_against_redefining_existing_example_group(new_example_group)
+          existing_example_group = find_shared_example_group(new_example_group.description)
+          return unless existing_example_group
+          return if new_example_group.equal?(existing_example_group)
+          return if spec_path(new_example_group) == spec_path(existing_example_group)
+          raise ArgumentError.new("Shared Example '#{existing_example_group.description}' already exists")
+        end
+
+        def spec_path(example_group)
+          File.expand_path(example_group.spec_path)
+        end
+      end
+      include ExampleGroupMethods
+      public :include
+
+      def initialize(*args, &example_group_block)
+        describe(*args)
+        @example_group_block = example_group_block
+        self.class.add_shared_example_group(self)
+      end
+
+      def included(mod) # :nodoc:
+        mod.module_eval(&@example_group_block)
+      end
+
+      def execute_in_class_hierarchy(superclass_last=false)
+        classes = [self]
+        superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods)
+        classes.each do |example_group|
+          yield example_group
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/expectations.rb b/vendor/gems/rspec/lib/spec/expectations.rb
new file mode 100644
index 0000000..65ea474
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/expectations.rb
@@ -0,0 +1,56 @@
+require 'spec/matchers'
+require 'spec/expectations/errors'
+require 'spec/expectations/extensions'
+require 'spec/expectations/handler'
+
+module Spec
+  
+  # Spec::Expectations lets you set expectations on your objects.
+  #
+  #   result.should == 37
+  #   team.should have(11).players_on_the_field
+  #
+  # == How Expectations work.
+  #
+  # Spec::Expectations adds two methods to Object:
+  #
+  #   should(matcher=nil)
+  #   should_not(matcher=nil)
+  #
+  # Both methods take an optional Expression Matcher (See Spec::Matchers).
+  #
+  # When +should+ receives an Expression Matcher, it calls <tt>matches?(self)</tt>. If
+  # it returns +true+, the spec passes and execution continues. If it returns
+  # +false+, then the spec fails with the message returned by <tt>matcher.failure_message</tt>.
+  #
+  # Similarly, when +should_not+ receives a matcher, it calls <tt>matches?(self)</tt>. If
+  # it returns +false+, the spec passes and execution continues. If it returns
+  # +true+, then the spec fails with the message returned by <tt>matcher.negative_failure_message</tt>.
+  #
+  # RSpec ships with a standard set of useful matchers, and writing your own
+  # matchers is quite simple. See Spec::Matchers for details.
+  module Expectations
+    class << self
+      attr_accessor :differ
+
+      # raises a Spec::Expectations::ExpectationNotMetError with message
+      #
+      # When a differ has been assigned and fail_with is passed
+      # <code>expected</code> and <code>target</code>, passes them
+      # to the differ to append a diff message to the failure message.
+      def fail_with(message, expected=nil, target=nil) # :nodoc:
+        if Array === message && message.length == 3
+          message, expected, target = message[0], message[1], message[2]
+        end
+        unless (differ.nil? || expected.nil? || target.nil?)
+          if expected.is_a?(String)
+            message << "\nDiff:" << self.differ.diff_as_string(target.to_s, expected)
+          elsif !target.is_a?(Proc)
+            message << "\nDiff:" << self.differ.diff_as_object(target, expected)
+          end
+        end
+        Kernel::raise(Spec::Expectations::ExpectationNotMetError.new(message))
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/expectations/differs/default.rb b/vendor/gems/rspec/lib/spec/expectations/differs/default.rb
new file mode 100644
index 0000000..a5eb1bb
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/expectations/differs/default.rb
@@ -0,0 +1,66 @@
+begin
+  require 'rubygems'
+  require 'diff/lcs' #necessary due to loading bug on some machines - not sure why - DaC
+  require 'diff/lcs/hunk'
+rescue LoadError ; raise "You must gem install diff-lcs to use diffing" ; end
+
+require 'pp'
+
+module Spec
+  module Expectations
+    module Differs
+
+      # TODO add some rdoc
+      class Default
+        def initialize(options)
+          @options = options
+        end
+
+        # This is snagged from diff/lcs/ldiff.rb (which is a commandline tool)
+        def diff_as_string(data_old, data_new)
+          data_old = data_old.split(/\n/).map! { |e| e.chomp }
+          data_new = data_new.split(/\n/).map! { |e| e.chomp }
+          output = ""
+          diffs = Diff::LCS.diff(data_old, data_new)
+          return output if diffs.empty?
+          oldhunk = hunk = nil  
+          file_length_difference = 0
+          diffs.each do |piece|
+            begin
+              hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, context_lines,
+                                         file_length_difference)
+              file_length_difference = hunk.file_length_difference      
+              next unless oldhunk      
+              # Hunks may overlap, which is why we need to be careful when our
+              # diff includes lines of context. Otherwise, we might print
+              # redundant lines.
+              if (context_lines > 0) and hunk.overlaps?(oldhunk)
+                hunk.unshift(oldhunk)
+              else
+                output << oldhunk.diff(format)
+              end
+            ensure
+              oldhunk = hunk
+              output << "\n"
+            end
+          end  
+          #Handle the last remaining hunk
+          output << oldhunk.diff(format) << "\n"
+        end  
+
+        def diff_as_object(target,expected)
+          diff_as_string(PP.pp(target,""), PP.pp(expected,""))
+        end
+
+        protected
+        def format
+          @options.diff_format
+        end
+
+        def context_lines
+          @options.context_lines
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/expectations/errors.rb b/vendor/gems/rspec/lib/spec/expectations/errors.rb
new file mode 100644
index 0000000..1fabd10
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/expectations/errors.rb
@@ -0,0 +1,12 @@
+module Spec
+  module Expectations
+    # If Test::Unit is loaed, we'll use its error as baseclass, so that Test::Unit
+    # will report unmet RSpec expectations as failures rather than errors.
+    superclass = ['Test::Unit::AssertionFailedError', '::StandardError'].map do |c|
+      eval(c) rescue nil
+    end.compact.first
+    
+    class ExpectationNotMetError < superclass
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/expectations/extensions.rb b/vendor/gems/rspec/lib/spec/expectations/extensions.rb
new file mode 100644
index 0000000..60c9b9e
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/expectations/extensions.rb
@@ -0,0 +1,2 @@
+require 'spec/expectations/extensions/object'
+require 'spec/expectations/extensions/string_and_symbol'
diff --git a/vendor/gems/rspec/lib/spec/expectations/extensions/object.rb b/vendor/gems/rspec/lib/spec/expectations/extensions/object.rb
new file mode 100644
index 0000000..a3925bb
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/expectations/extensions/object.rb
@@ -0,0 +1,71 @@
+module Spec
+  module Expectations
+    # rspec adds #should and #should_not to every Object (and,
+    # implicitly, every Class).
+    module ObjectExpectations
+      # :call-seq:
+      #   should(matcher)
+      #   should == expected
+      #   should === expected
+      #   should =~ expected
+      #
+      #   receiver.should(matcher)
+      #     => Passes if matcher.matches?(receiver)
+      #
+      #   receiver.should == expected #any value
+      #     => Passes if (receiver == expected)
+      #
+      #   receiver.should === expected #any value
+      #     => Passes if (receiver === expected)
+      #
+      #   receiver.should =~ regexp
+      #     => Passes if (receiver =~ regexp)
+      #
+      # See Spec::Matchers for more information about matchers
+      #
+      # == Warning
+      #
+      # NOTE that this does NOT support receiver.should != expected.
+      # Instead, use receiver.should_not == expected
+      def should(matcher = :default_parameter, &block)
+        if :default_parameter == matcher
+          Spec::Matchers::PositiveOperatorMatcher.new(self)
+        else
+          ExpectationMatcherHandler.handle_matcher(self, matcher, &block)
+        end
+      end
+
+      # :call-seq:
+      #   should_not(matcher)
+      #   should_not == expected
+      #   should_not === expected
+      #   should_not =~ expected
+      #
+      #   receiver.should_not(matcher)
+      #     => Passes unless matcher.matches?(receiver)
+      #
+      #   receiver.should_not == expected
+      #     => Passes unless (receiver == expected)
+      #
+      #   receiver.should_not === expected
+      #     => Passes unless (receiver === expected)
+      #
+      #   receiver.should_not =~ regexp
+      #     => Passes unless (receiver =~ regexp)
+      #
+      # See Spec::Matchers for more information about matchers
+      def should_not(matcher = :default_parameter, &block)
+        if :default_parameter == matcher
+          Spec::Matchers::NegativeOperatorMatcher.new(self)
+        else
+          NegativeExpectationMatcherHandler.handle_matcher(self, matcher, &block)
+        end
+      end
+
+    end
+  end
+end
+
+class Object
+  include Spec::Expectations::ObjectExpectations
+end
diff --git a/vendor/gems/rspec/lib/spec/expectations/extensions/string_and_symbol.rb b/vendor/gems/rspec/lib/spec/expectations/extensions/string_and_symbol.rb
new file mode 100644
index 0000000..29cfbdd
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/expectations/extensions/string_and_symbol.rb
@@ -0,0 +1,17 @@
+module Spec
+  module Expectations
+    module StringHelpers
+      def starts_with?(prefix)
+        to_s[0..(prefix.to_s.length - 1)] == prefix.to_s
+      end
+    end
+  end
+end
+
+class String
+  include Spec::Expectations::StringHelpers
+end
+
+class Symbol
+  include Spec::Expectations::StringHelpers
+end
diff --git a/vendor/gems/rspec/lib/spec/expectations/handler.rb b/vendor/gems/rspec/lib/spec/expectations/handler.rb
new file mode 100644
index 0000000..e6dce08
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/expectations/handler.rb
@@ -0,0 +1,52 @@
+module Spec
+  module Expectations
+    class InvalidMatcherError < ArgumentError; end        
+    
+    module MatcherHandlerHelper
+      def describe_matcher(matcher)
+        matcher.respond_to?(:description) ? matcher.description : "[#{matcher.class.name} does not provide a description]"
+      end
+    end
+    
+    class ExpectationMatcherHandler        
+      class << self
+        include MatcherHandlerHelper
+        def handle_matcher(actual, matcher, &block)
+          unless matcher.respond_to?(:matches?)
+            raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
+          end
+          
+          match = matcher.matches?(actual, &block)
+          ::Spec::Matchers.generated_description = "should #{describe_matcher(matcher)}"
+          Spec::Expectations.fail_with(matcher.failure_message) unless match
+        end
+      end
+    end
+
+    class NegativeExpectationMatcherHandler
+      class << self
+        include MatcherHandlerHelper
+        def handle_matcher(actual, matcher, &block)
+          unless matcher.respond_to?(:matches?)
+            raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
+          end
+
+          unless matcher.respond_to?(:negative_failure_message)
+            Spec::Expectations.fail_with(
+<<-EOF
+Matcher does not support should_not.
+See Spec::Matchers for more information
+about matchers.
+EOF
+)
+          end
+          match = matcher.matches?(actual, &block)
+          ::Spec::Matchers.generated_description = "should not #{describe_matcher(matcher)}"
+          Spec::Expectations.fail_with(matcher.negative_failure_message) if match
+        end
+      end
+    end
+
+  end
+end
+
diff --git a/vendor/gems/rspec/lib/spec/extensions.rb b/vendor/gems/rspec/lib/spec/extensions.rb
new file mode 100755
index 0000000..9a313d0
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/extensions.rb
@@ -0,0 +1,3 @@
+require 'spec/extensions/object'
+require 'spec/extensions/class'
+require 'spec/extensions/main'
diff --git a/vendor/gems/rspec/lib/spec/extensions/class.rb b/vendor/gems/rspec/lib/spec/extensions/class.rb
new file mode 100644
index 0000000..30730f8
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/extensions/class.rb
@@ -0,0 +1,24 @@
+class Class
+  # Creates a new subclass of self, with a name "under" our own name.
+  # Example:
+  #
+  #   x = Foo::Bar.subclass('Zap'){}
+  #   x.name # => Foo::Bar::Zap_1
+  #   x.superclass.name # => Foo::Bar
+  def subclass(base_name, &body)
+    klass = Class.new(self)
+    class_name = "#{base_name}_#{class_count!}"
+    instance_eval do
+      const_set(class_name, klass)
+    end
+    klass.instance_eval(&body)
+    klass
+  end
+
+  private
+  def class_count!
+    @class_count ||= 0
+    @class_count += 1
+    @class_count
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/extensions/main.rb b/vendor/gems/rspec/lib/spec/extensions/main.rb
new file mode 100644
index 0000000..281cbf8
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/extensions/main.rb
@@ -0,0 +1,102 @@
+module Spec
+  module Extensions
+    module Main
+      # Creates and returns a class that includes the ExampleGroupMethods
+      # module. Which ExampleGroup type is created depends on the directory of the file
+      # calling this method. For example, Spec::Rails will use different
+      # classes for specs living in <tt>spec/models</tt>,
+      # <tt>spec/helpers</tt>, <tt>spec/views</tt> and
+      # <tt>spec/controllers</tt>.
+      #
+      # It is also possible to override autodiscovery of the example group
+      # type with an options Hash as the last argument:
+      #
+      #   describe "name", :type => :something_special do ...
+      #
+      # The reason for using different behaviour classes is to have different
+      # matcher methods available from within the <tt>describe</tt> block.
+      #
+      # See Spec::Example::ExampleFactory#register for details about how to
+      # register special implementations.
+      #
+      def describe(*args, &block)
+        raise ArgumentError if args.empty?
+        raise ArgumentError unless block
+        args << {} unless Hash === args.last
+        args.last[:spec_path] = caller(0)[1]
+        Spec::Example::ExampleGroupFactory.create_example_group(*args, &block)
+      end
+      alias :context :describe
+      
+      # Creates an example group that can be shared by other example groups
+      #
+      # == Examples
+      #
+      #  share_examples_for "All Editions" do
+      #    it "all editions behaviour" ...
+      #  end
+      #
+      #  describe SmallEdition do
+      #    it_should_behave_like "All Editions"
+      #  
+      #    it "should do small edition stuff" do
+      #      ...
+      #    end
+      #  end
+      def share_examples_for(name, &block)
+        describe(name, :shared => true, &block)
+      end
+      
+      alias :shared_examples_for :share_examples_for
+      
+      # Creates a Shared Example Group and assigns it to a constant
+      #
+      #  share_as :AllEditions do
+      #    it "should do all editions stuff" ...
+      #  end
+      #
+      #  describe SmallEdition do
+      #    it_should_behave_like AllEditions
+      #  
+      #    it "should do small edition stuff" do
+      #      ...
+      #    end
+      #  end
+      #
+      # And, for those of you who prefer to use something more like Ruby, you
+      # can just include the module directly
+      #
+      #  describe SmallEdition do
+      #    include AllEditions
+      #  
+      #    it "should do small edition stuff" do
+      #      ...
+      #    end
+      #  end
+      def share_as(name, &block)
+        begin
+          Object.const_set(name, share_examples_for(name, &block))
+        rescue NameError => e
+          raise NameError.new(e.message + "\nThe first argument to share_as must be a legal name for a constant\n")
+        end
+      end
+
+    private
+    
+      def rspec_options
+        $rspec_options ||= begin; \
+          parser = ::Spec::Runner::OptionParser.new(STDERR, STDOUT); \
+          parser.order!(ARGV); \
+          $rspec_options = parser.options; \
+        end
+        $rspec_options
+      end
+      
+      def init_rspec_options(options)
+        $rspec_options = options if $rspec_options.nil?
+      end
+    end
+  end
+end
+
+include Spec::Extensions::Main
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/extensions/object.rb b/vendor/gems/rspec/lib/spec/extensions/object.rb
new file mode 100755
index 0000000..e9f6364
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/extensions/object.rb
@@ -0,0 +1,10 @@
+class Object
+  def args_and_options(*args)
+    options = Hash === args.last ? args.pop : {}
+    return args, options
+  end
+
+  def metaclass
+    class << self; self; end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/interop/test.rb b/vendor/gems/rspec/lib/spec/interop/test.rb
new file mode 100644
index 0000000..afa1613
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/interop/test.rb
@@ -0,0 +1,12 @@
+require 'test/unit'
+require 'test/unit/testresult'
+
+require 'spec/interop/test/unit/testcase'
+require 'spec/interop/test/unit/testsuite_adapter'
+require 'spec/interop/test/unit/autorunner'
+require 'spec/interop/test/unit/testresult'
+require 'spec/interop/test/unit/ui/console/testrunner'
+
+Spec::Example::ExampleGroupFactory.default(Test::Unit::TestCase)
+
+Test::Unit.run = true
diff --git a/vendor/gems/rspec/lib/spec/interop/test/unit/autorunner.rb b/vendor/gems/rspec/lib/spec/interop/test/unit/autorunner.rb
new file mode 100644
index 0000000..3944e69
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/interop/test/unit/autorunner.rb
@@ -0,0 +1,6 @@
+class Test::Unit::AutoRunner
+  remove_method :process_args
+  def process_args(argv)
+    true
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/interop/test/unit/testcase.rb b/vendor/gems/rspec/lib/spec/interop/test/unit/testcase.rb
new file mode 100644
index 0000000..b32a820
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/interop/test/unit/testcase.rb
@@ -0,0 +1,61 @@
+require 'test/unit/testcase'
+
+module Test
+  module Unit
+    # This extension of the standard Test::Unit::TestCase makes RSpec
+    # available from within, so that you can do things like:
+    #
+    # require 'test/unit'
+    # require 'spec'
+    #
+    # class MyTest < Test::Unit::TestCase
+    #   it "should work with Test::Unit assertions" do
+    #     assert_equal 4, 2+1
+    #   end
+    #
+    #   def test_should_work_with_rspec_expectations
+    #     (3+1).should == 5
+    #   end
+    # end
+    #
+    # See also Spec::Example::ExampleGroup
+    class TestCase
+      extend Spec::Example::ExampleGroupMethods
+      include Spec::Example::ExampleMethods
+
+      before(:each) {setup}
+      after(:each) {teardown}
+
+      class << self
+        def suite
+          Test::Unit::TestSuiteAdapter.new(self)
+        end
+
+        def example_method?(method_name)
+          should_method?(method_name) || test_method?(method_name)
+        end
+
+        def test_method?(method_name)
+          method_name =~ /^test[_A-Z]./ && (
+            instance_method(method_name).arity == 0 ||
+            instance_method(method_name).arity == -1
+          )
+        end
+      end
+
+      def initialize(defined_description, &implementation)
+        @_defined_description = defined_description
+        @_implementation = implementation
+
+        @_result = ::Test::Unit::TestResult.new
+        # @method_name is important to set here because it "complies" with Test::Unit's interface.
+        # Some Test::Unit extensions depend on @method_name being present.
+        @method_name = @_defined_description
+      end
+
+      def run(ignore_this_argument=nil)
+        super()
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/interop/test/unit/testresult.rb b/vendor/gems/rspec/lib/spec/interop/test/unit/testresult.rb
new file mode 100644
index 0000000..1386dc7
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/interop/test/unit/testresult.rb
@@ -0,0 +1,6 @@
+class Test::Unit::TestResult
+  alias_method :tu_passed?, :passed?
+  def passed?
+    return tu_passed? & ::Spec.run
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/interop/test/unit/testsuite_adapter.rb b/vendor/gems/rspec/lib/spec/interop/test/unit/testsuite_adapter.rb
new file mode 100644
index 0000000..7c0ed09
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/interop/test/unit/testsuite_adapter.rb
@@ -0,0 +1,34 @@
+module Test
+  module Unit
+    class TestSuiteAdapter < TestSuite
+      attr_reader :example_group, :examples
+      alias_method :tests, :examples
+      def initialize(example_group)
+        @example_group = example_group
+        @examples = example_group.examples
+      end
+
+      def name
+        example_group.description
+      end
+
+      def run(*args)
+        return true unless args.empty?
+        example_group.run
+      end
+
+      def size
+        example_group.number_of_examples
+      end
+
+      def delete(example)
+        examples.delete example
+      end
+
+      def empty?
+        examples.empty?
+      end
+    end
+  end
+end
+
diff --git a/vendor/gems/rspec/lib/spec/interop/test/unit/ui/console/testrunner.rb b/vendor/gems/rspec/lib/spec/interop/test/unit/ui/console/testrunner.rb
new file mode 100644
index 0000000..8e9995e
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/interop/test/unit/ui/console/testrunner.rb
@@ -0,0 +1,61 @@
+require 'test/unit/ui/console/testrunner'
+
+module Test
+  module Unit
+    module UI
+      module Console
+        class TestRunner
+
+          alias_method :started_without_rspec, :started
+          def started_with_rspec(result)
+            @result = result
+            @need_to_output_started = true
+          end
+          alias_method :started, :started_with_rspec
+
+          alias_method :test_started_without_rspec, :test_started
+          def test_started_with_rspec(name)
+            if @need_to_output_started
+              if @rspec_io
+                @rspec_io.rewind
+                output(@rspec_io.read)
+              end
+              output("Started")
+              @need_to_output_started = false
+            end
+            test_started_without_rspec(name)
+          end
+          alias_method :test_started, :test_started_with_rspec
+
+          alias_method :test_finished_without_rspec, :test_finished
+          def test_finished_with_rspec(name)
+            test_finished_without_rspec(name)
+            @ran_test = true
+          end
+          alias_method :test_finished, :test_finished_with_rspec
+
+          alias_method :finished_without_rspec, :finished
+          def finished_with_rspec(elapsed_time)
+            @ran_test ||= false
+            if @ran_test
+              finished_without_rspec(elapsed_time)
+            end
+          end
+          alias_method :finished, :finished_with_rspec
+          
+          alias_method :setup_mediator_without_rspec, :setup_mediator
+          def setup_mediator_with_rspec
+            orig_io = @io
+            @io = StringIO.new
+            setup_mediator_without_rspec
+          ensure
+            @rspec_io = @io
+            @io = orig_io
+          end
+          alias_method :setup_mediator, :setup_mediator_with_rspec
+          
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers.rb b/vendor/gems/rspec/lib/spec/matchers.rb
new file mode 100644
index 0000000..afae5ae
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers.rb
@@ -0,0 +1,156 @@
+require 'spec/matchers/simple_matcher'
+require 'spec/matchers/be'
+require 'spec/matchers/be_close'
+require 'spec/matchers/change'
+require 'spec/matchers/eql'
+require 'spec/matchers/equal'
+require 'spec/matchers/exist'
+require 'spec/matchers/has'
+require 'spec/matchers/have'
+require 'spec/matchers/include'
+require 'spec/matchers/match'
+require 'spec/matchers/raise_error'
+require 'spec/matchers/respond_to'
+require 'spec/matchers/satisfy'
+require 'spec/matchers/throw_symbol'
+require 'spec/matchers/operator_matcher'
+
+module Spec
+
+  # RSpec ships with a number of useful Expression Matchers. An Expression Matcher
+  # is any object that responds to the following methods:
+  #
+  #   matches?(actual)
+  #   failure_message
+  #   negative_failure_message #optional
+  #   description #optional
+  #
+  # See Spec::Expectations to learn how to use these as Expectation Matchers.
+  # See Spec::Mocks to learn how to use them as Mock Argument Constraints.
+  #
+  # == Predicates
+  #
+  # In addition to those Expression Matchers that are defined explicitly, RSpec will
+  # create custom Matchers on the fly for any arbitrary predicate, giving your specs
+  # a much more natural language feel. 
+  #
+  # A Ruby predicate is a method that ends with a "?" and returns true or false.
+  # Common examples are +empty?+, +nil?+, and +instance_of?+.
+  #
+  # All you need to do is write +should be_+ followed by the predicate without
+  # the question mark, and RSpec will figure it out from there. For example:
+  #
+  #   [].should be_empty => [].empty? #passes
+  #   [].should_not be_empty => [].empty? #fails
+  #
+  # In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_"
+  # and "be_an_", making your specs read much more naturally:
+  #
+  #   "a string".should be_an_instance_of(String) =>"a string".instance_of?(String) #passes
+  #
+  #   3.should be_a_kind_of(Fixnum) => 3.kind_of?(Numeric) #passes
+  #   3.should be_a_kind_of(Numeric) => 3.kind_of?(Numeric) #passes
+  #   3.should be_an_instance_of(Fixnum) => 3.instance_of?(Fixnum) #passes
+  #   3.should_not be_instance_of(Numeric) => 3.instance_of?(Numeric) #fails
+  #
+  # RSpec will also create custom matchers for predicates like +has_key?+. To
+  # use this feature, just state that the object should have_key(:key) and RSpec will
+  # call has_key?(:key) on the target. For example:
+  #
+  #   {:a => "A"}.should have_key(:a) => {:a => "A"}.has_key?(:a) #passes
+  #   {:a => "A"}.should have_key(:b) => {:a => "A"}.has_key?(:b) #fails
+  #
+  # You can use this feature to invoke any predicate that begins with "has_", whether it is
+  # part of the Ruby libraries (like +Hash#has_key?+) or a method you wrote on your own class.
+  #
+  # == Custom Expectation Matchers
+  #
+  # When you find that none of the stock Expectation Matchers provide a natural
+  # feeling expectation, you can very easily write your own.
+  #
+  # For example, imagine that you are writing a game in which players can
+  # be in various zones on a virtual board. To specify that bob should
+  # be in zone 4, you could say:
+  #
+  #   bob.current_zone.should eql(Zone.new("4"))
+  #
+  # But you might find it more expressive to say:
+  #
+  #   bob.should be_in_zone("4")
+  #
+  # and/or
+  #
+  #   bob.should_not be_in_zone("3")
+  #
+  # To do this, you would need to write a class like this:
+  #
+  #   class BeInZone
+  #     def initialize(expected)
+  #       @expected = expected
+  #     end
+  #     def matches?(target)
+  #       @target = target
+  #       @target.current_zone.eql?(Zone.new(@expected))
+  #     end
+  #     def failure_message
+  #       "expected #{@target.inspect} to be in Zone #{@expected}"
+  #     end
+  #     def negative_failure_message
+  #       "expected #{@target.inspect} not to be in Zone #{@expected}"
+  #     end
+  #   end
+  #
+  # ... and a method like this:
+  #
+  #   def be_in_zone(expected)
+  #     BeInZone.new(expected)
+  #   end
+  #
+  # And then expose the method to your specs. This is normally done
+  # by including the method and the class in a module, which is then
+  # included in your spec:
+  #
+  #   module CustomGameMatchers
+  #     class BeInZone
+  #       ...
+  #     end
+  #
+  #     def be_in_zone(expected)
+  #       ...
+  #     end
+  #   end
+  #
+  #   describe "Player behaviour" do
+  #     include CustomGameMatchers
+  #     ...
+  #   end
+  #
+  # or you can include in globally in a spec_helper.rb file <tt>require</tt>d
+  # from your spec file(s):
+  #
+  #   Spec::Runner.configure do |config|
+  #     config.include(CustomGameMatchers)
+  #   end
+  #
+  module Matchers
+    module ModuleMethods
+      attr_accessor :generated_description
+
+      def clear_generated_description
+        self.generated_description = nil
+      end
+    end
+
+    extend ModuleMethods
+
+    def method_missing(sym, *args, &block) # :nodoc:
+      return Matchers::Be.new(sym, *args) if sym.starts_with?("be_")
+      return Matchers::Has.new(sym, *args) if sym.starts_with?("have_")
+      super
+    end
+
+    class MatcherError < StandardError
+    end
+    
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/be.rb b/vendor/gems/rspec/lib/spec/matchers/be.rb
new file mode 100644
index 0000000..2b25b11
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/be.rb
@@ -0,0 +1,224 @@
+module Spec
+  module Matchers
+    
+    class Be #:nodoc:
+      def initialize(*args)
+        if args.empty?
+          @expected = :satisfy_if
+        else
+          @expected = parse_expected(args.shift)
+        end
+        @args = args
+        @comparison = ""
+      end
+      
+      def matches?(actual)
+        @actual = actual
+        if handling_predicate?
+          begin
+            return @result = actual.__send__(predicate, *@args)
+          rescue => predicate_error
+            # This clause should be empty, but rcov will not report it as covered
+            # unless something (anything) is executed within the clause
+            rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
+          end
+
+          # This supports should_exist > target.exists? in the old world.
+          # We should consider deprecating that ability as in the new world
+          # you can't write "should exist" unless you have your own custom matcher.
+          begin
+            return @result = actual.__send__(present_tense_predicate, *@args)
+          rescue
+            raise predicate_error
+          end
+        else
+          return match_or_compare
+        end
+      end
+      
+      def failure_message
+        return "expected #{@comparison}#{expected}, got #{@actual.inspect}" unless handling_predicate?
+        return "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}"
+      end
+      
+      def negative_failure_message
+        return "expected not #{expected}, got #{@actual.inspect}" unless handling_predicate?
+        return "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}"
+      end
+      
+      def expected
+        return "if to be satisfied" if @expected == :satisfy_if
+        return true if @expected == :true
+        return false if @expected == :false
+        return "nil" if @expected == :nil
+        return @expected.inspect
+      end
+      
+      def match_or_compare
+        return @actual ? true : false if @expected == :satisfy_if
+        return @actual == true if @expected == :true
+        return @actual == false if @expected == :false
+        return @actual.nil? if @expected == :nil
+        return @actual < @expected if @less_than
+        return @actual <= @expected if @less_than_or_equal
+        return @actual >= @expected if @greater_than_or_equal
+        return @actual > @expected if @greater_than
+        return @actual == @expected if @double_equal
+        return @actual === @expected if @triple_equal
+        return @actual.equal?(@expected)
+      end
+      
+      def ==(expected)
+        @prefix = "be "
+        @double_equal = true
+        @comparison = "== "
+        @expected = expected
+        self
+      end
+
+      def ===(expected)
+        @prefix = "be "
+        @triple_equal = true
+        @comparison = "=== "
+        @expected = expected
+        self
+      end
+
+      def <(expected)
+        @prefix = "be "
+        @less_than = true
+        @comparison = "< "
+        @expected = expected
+        self
+      end
+
+      def <=(expected)
+        @prefix = "be "
+        @less_than_or_equal = true
+        @comparison = "<= "
+        @expected = expected
+        self
+      end
+
+      def >=(expected)
+        @prefix = "be "
+        @greater_than_or_equal = true
+        @comparison = ">= "
+        @expected = expected
+        self
+      end
+
+      def >(expected)
+        @prefix = "be "
+        @greater_than = true
+        @comparison = "> "
+        @expected = expected
+        self
+      end
+      
+      def description
+        "#{prefix_to_sentence}#{comparison}#{expected_to_sentence}#{args_to_sentence}"
+      end
+
+      private
+        def parse_expected(expected)
+          if Symbol === expected
+            @handling_predicate = true
+            ["be_an_","be_a_","be_"].each do |prefix|
+              if expected.starts_with?(prefix)
+                @prefix = prefix
+                return "#{expected.to_s.sub(@prefix,"")}".to_sym
+              end
+            end
+          end
+          @prefix = ""
+          return expected
+        end
+        
+        def handling_predicate?
+          return false if [:true, :false, :nil].include?(@expected)
+          return @handling_predicate
+        end
+
+        def predicate
+          "#{@expected.to_s}?".to_sym
+        end
+        
+        def present_tense_predicate
+          "#{@expected.to_s}s?".to_sym
+        end
+        
+        def args_to_s
+          return "" if @args.empty?
+          inspected_args = @args.collect{|a| a.inspect}
+          return "(#{inspected_args.join(', ')})"
+        end
+        
+        def comparison
+          @comparison
+        end
+        
+        def expected_to_sentence
+          split_words(@expected)
+        end
+        
+        def prefix_to_sentence
+          split_words(@prefix)
+        end
+
+        def split_words(sym)
+          sym.to_s.gsub(/_/,' ')
+        end
+
+        def args_to_sentence
+          case @args.length
+            when 0
+              ""
+            when 1
+              " #{@args[0]}"
+            else
+              " #{@args[0...-1].join(', ')} and #{@args[-1]}"
+          end
+        end
+        
+    end
+ 
+    # :call-seq:
+    #   should be
+    #   should be_true
+    #   should be_false
+    #   should be_nil
+    #   should be_arbitrary_predicate(*args)
+    #   should_not be_nil
+    #   should_not be_arbitrary_predicate(*args)
+    #
+    # Given true, false, or nil, will pass if actual is
+    # true, false or nil (respectively). Given no args means
+    # the caller should satisfy an if condition (to be or not to be). 
+    #
+    # Predicates are any Ruby method that ends in a "?" and returns true or false.
+    # Given be_ followed by arbitrary_predicate (without the "?"), RSpec will match
+    # convert that into a query against the target object.
+    #
+    # The arbitrary_predicate feature will handle any predicate
+    # prefixed with "be_an_" (e.g. be_an_instance_of), "be_a_" (e.g. be_a_kind_of)
+    # or "be_" (e.g. be_empty), letting you choose the prefix that best suits the predicate.
+    #
+    # == Examples 
+    #
+    #   target.should be
+    #   target.should be_true
+    #   target.should be_false
+    #   target.should be_nil
+    #   target.should_not be_nil
+    #
+    #   collection.should be_empty #passes if target.empty?
+    #   "this string".should be_an_intance_of(String)
+    #
+    #   target.should_not be_empty #passes unless target.empty?
+    #   target.should_not be_old_enough(16) #passes unless target.old_enough?(16)
+    def be(*args)
+      Matchers::Be.new(*args)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/be_close.rb b/vendor/gems/rspec/lib/spec/matchers/be_close.rb
new file mode 100644
index 0000000..7763eb9
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/be_close.rb
@@ -0,0 +1,37 @@
+module Spec
+  module Matchers
+
+    class BeClose #:nodoc:
+      def initialize(expected, delta)
+        @expected = expected
+        @delta = delta
+      end
+      
+      def matches?(actual)
+        @actual = actual
+        (@actual - @expected).abs < @delta
+      end
+      
+      def failure_message
+        "expected #{@expected} +/- (< #{@delta}), got #{@actual}"
+      end
+      
+      def description
+        "be close to #{@expected} (within +- #{@delta})"
+      end
+    end
+    
+    # :call-seq:
+    #   should be_close(expected, delta)
+    #   should_not be_close(expected, delta)
+    #
+    # Passes if actual == expected +/- delta
+    #
+    # == Example
+    #
+    #   result.should be_close(3.0, 0.5)
+    def be_close(expected, delta)
+      Matchers::BeClose.new(expected, delta)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/change.rb b/vendor/gems/rspec/lib/spec/matchers/change.rb
new file mode 100644
index 0000000..784e516
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/change.rb
@@ -0,0 +1,144 @@
+module Spec
+  module Matchers
+    
+    #Based on patch from Wilson Bilkovich
+    class Change #:nodoc:
+      def initialize(receiver=nil, message=nil, &block)
+        @receiver = receiver
+        @message = message
+        @block = block
+      end
+      
+      def matches?(target, &block)
+        if block
+          raise MatcherError.new(<<-EOF
+block passed to should or should_not change must use {} instead of do/end
+EOF
+)
+        end
+        @target = target
+        execute_change
+        return false if @from && (@from != @before)
+        return false if @to && (@to != @after)
+        return (@before + @amount == @after) if @amount
+        return ((@after - @before) >= @minimum) if @minimum
+        return ((@after - @before) <= @maximum) if @maximum        
+        return @before != @after
+      end
+      
+      def execute_change
+        @before = @block.nil? ? @receiver.send(@message) : @block.call
+        @target.call
+        @after = @block.nil? ? @receiver.send(@message) : @block.call
+      end
+      
+      def failure_message
+        if @to
+          "#{result} should have been changed to #{@to.inspect}, but is now #{@after.inspect}"
+        elsif @from
+          "#{result} should have initially been #{@from.inspect}, but was #{@before.inspect}"
+        elsif @amount
+          "#{result} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}"
+        elsif @minimum
+          "#{result} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}"
+        elsif @maximum
+          "#{result} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}"
+        else
+          "#{result} should have changed, but is still #{@before.inspect}"
+        end
+      end
+      
+      def result
+        @message || "result"
+      end
+      
+      def actual_delta
+        @after - @before
+      end
+      
+      def negative_failure_message
+        "#{result} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}"
+      end
+      
+      def by(amount)
+        @amount = amount
+        self
+      end
+      
+      def by_at_least(minimum)
+        @minimum = minimum
+        self
+      end
+      
+      def by_at_most(maximum)
+        @maximum = maximum
+        self
+      end      
+      
+      def to(to)
+        @to = to
+        self
+      end
+      
+      def from (from)
+        @from = from
+        self
+      end
+    end
+    
+    # :call-seq:
+    #   should change(receiver, message, &block)
+    #   should change(receiver, message, &block).by(value)
+    #   should change(receiver, message, &block).from(old).to(new)
+    #   should_not change(receiver, message, &block)
+    #
+    # Allows you to specify that a Proc will cause some value to change.
+    #
+    # == Examples
+    #
+    #   lambda {
+    #     team.add_player(player) 
+    #   }.should change(roster, :count)
+    #
+    #   lambda {
+    #     team.add_player(player) 
+    #   }.should change(roster, :count).by(1)
+    #
+    #   lambda {
+    #     team.add_player(player) 
+    #   }.should change(roster, :count).by_at_least(1)
+    #
+    #   lambda {
+    #     team.add_player(player)
+    #   }.should change(roster, :count).by_at_most(1)    
+    #
+    #   string = "string"
+    #   lambda {
+    #     string.reverse
+    #   }.should change { string }.from("string").to("gnirts")
+    #
+    #   lambda {
+    #     person.happy_birthday
+    #   }.should change(person, :birthday).from(32).to(33)
+    #       
+    #   lambda {
+    #     employee.develop_great_new_social_networking_app
+    #   }.should change(employee, :title).from("Mail Clerk").to("CEO")
+    #
+    # Evaluates +receiver.message+ or +block+ before and
+    # after it evaluates the c object (generated by the lambdas in the examples above).
+    #
+    # Then compares the values before and after the +receiver.message+ and
+    # evaluates the difference compared to the expected difference.
+    #
+    # == Warning
+    # +should_not+ +change+ only supports the form with no subsequent calls to
+    # +by+, +by_at_least+, +by_at_most+, +to+ or +from+.
+    #
+    # blocks passed to +should+ +change+ and +should_not+ +change+
+    # must use the <tt>{}</tt> form (<tt>do/end</tt> is not supported)
+    def change(target=nil, message=nil, &block)
+      Matchers::Change.new(target, message, &block)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/eql.rb b/vendor/gems/rspec/lib/spec/matchers/eql.rb
new file mode 100644
index 0000000..280ca54
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/eql.rb
@@ -0,0 +1,43 @@
+module Spec
+  module Matchers
+  
+    class Eql #:nodoc:
+      def initialize(expected)
+        @expected = expected
+      end
+  
+      def matches?(actual)
+        @actual = actual
+        @actual.eql?(@expected)
+      end
+
+      def failure_message
+        return "expected #{@expected.inspect}, got #{@actual.inspect} (using .eql?)", @expected, @actual
+      end
+      
+      def negative_failure_message
+        return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .eql?)", @expected, @actual
+      end
+
+      def description
+        "eql #{@expected.inspect}"
+      end
+    end
+    
+    # :call-seq:
+    #   should eql(expected)
+    #   should_not eql(expected)
+    #
+    # Passes if actual and expected are of equal value, but not necessarily the same object.
+    #
+    # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
+    #
+    # == Examples
+    #
+    #   5.should eql(5)
+    #   5.should_not eql(3)
+    def eql(expected)
+      Matchers::Eql.new(expected)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/equal.rb b/vendor/gems/rspec/lib/spec/matchers/equal.rb
new file mode 100644
index 0000000..4bfc749
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/equal.rb
@@ -0,0 +1,43 @@
+module Spec
+  module Matchers
+  
+    class Equal #:nodoc:
+      def initialize(expected)
+        @expected = expected
+      end
+  
+      def matches?(actual)
+        @actual = actual
+        @actual.equal?(@expected)
+      end
+
+      def failure_message
+        return "expected #{@expected.inspect}, got #{@actual.inspect} (using .equal?)", @expected, @actual
+      end
+
+      def negative_failure_message
+        return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .equal?)", @expected, @actual
+      end
+      
+      def description
+        "equal #{@expected.inspect}"
+      end
+    end
+    
+    # :call-seq:
+    #   should equal(expected)
+    #   should_not equal(expected)
+    #
+    # Passes if actual and expected are the same object (object identity).
+    #
+    # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
+    #
+    # == Examples
+    #
+    #   5.should equal(5) #Fixnums are equal
+    #   "5".should_not equal("5") #Strings that look the same are not the same object
+    def equal(expected)
+      Matchers::Equal.new(expected)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/exist.rb b/vendor/gems/rspec/lib/spec/matchers/exist.rb
new file mode 100644
index 0000000..a5a9111
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/exist.rb
@@ -0,0 +1,17 @@
+module Spec
+  module Matchers
+    class Exist
+      def matches? actual
+        @actual = actual
+        @actual.exist?
+      end
+      def failure_message
+        "expected #{@actual.inspect} to exist, but it doesn't."
+      end
+      def negative_failure_message
+        "expected #{@actual.inspect} to not exist, but it does."
+      end
+    end
+    def exist; Exist.new; end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/has.rb b/vendor/gems/rspec/lib/spec/matchers/has.rb
new file mode 100644
index 0000000..cc5a250
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/has.rb
@@ -0,0 +1,44 @@
+module Spec
+  module Matchers
+    
+    class Has #:nodoc:
+      def initialize(sym, *args)
+        @sym = sym
+        @args = args
+      end
+      
+      def matches?(target)
+        @target = target
+        begin
+          return target.send(predicate, *@args)
+        rescue => @error
+          # This clause should be empty, but rcov will not report it as covered
+          # unless something (anything) is executed within the clause
+          rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
+        end
+        return false
+      end
+      
+      def failure_message
+        raise @error if @error
+        "expected ##{predicate}(#{@args[0].inspect}) to return true, got false"
+      end
+      
+      def negative_failure_message
+        raise @error if @error
+        "expected ##{predicate}(#{@args[0].inspect}) to return false, got true"
+      end
+      
+      def description
+        "have key #{@args[0].inspect}"
+      end
+      
+      private
+        def predicate
+          "#{@sym.to_s.sub("have_","has_")}?".to_sym
+        end
+        
+    end
+ 
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/have.rb b/vendor/gems/rspec/lib/spec/matchers/have.rb
new file mode 100644
index 0000000..47454e3
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/have.rb
@@ -0,0 +1,145 @@
+module Spec
+  module Matchers
+    
+    class Have #:nodoc:
+      def initialize(expected, relativity=:exactly)
+        @expected = (expected == :no ? 0 : expected)
+        @relativity = relativity
+      end
+    
+      def relativities
+        @relativities ||= {
+          :exactly => "",
+          :at_least => "at least ",
+          :at_most => "at most "
+        }
+      end
+    
+      def method_missing(sym, *args, &block)
+        @collection_name = sym
+        @plural_collection_name = Inflector.pluralize(sym.to_s) if Object.const_defined?(:Inflector)
+        @args = args
+        @block = block
+        self
+      end
+    
+      def matches?(collection_owner)
+        if collection_owner.respond_to?(@collection_name)
+          collection = collection_owner.send(@collection_name, *@args, &@block)
+        elsif (@plural_collection_name && collection_owner.respond_to?(@plural_collection_name))
+          collection = collection_owner.send(@plural_collection_name, *@args, &@block)
+        elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size))
+          collection = collection_owner
+        else
+          collection_owner.send(@collection_name, *@args, &@block)
+        end
+        @actual = collection.size if collection.respond_to?(:size)
+        @actual = collection.length if collection.respond_to?(:length)
+        raise not_a_collection if @actual.nil?
+        return @actual >= @expected if @relativity == :at_least
+        return @actual <= @expected if @relativity == :at_most
+        return @actual == @expected
+      end
+      
+      def not_a_collection
+        "expected #{@collection_name} to be a collection but it does not respond to #length or #size"
+      end
+    
+      def failure_message
+        "expected #{relative_expectation} #{@collection_name}, got #{@actual}"
+      end
+
+      def negative_failure_message
+        if @relativity == :exactly
+          return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}"
+        elsif @relativity == :at_most
+          return <<-EOF
+Isn't life confusing enough?
+Instead of having to figure out the meaning of this:
+  should_not have_at_most(#{@expected}).#{@collection_name}
+We recommend that you use this instead:
+  should have_at_least(#{@expected + 1}).#{@collection_name}
+EOF
+        elsif @relativity == :at_least
+          return <<-EOF
+Isn't life confusing enough?
+Instead of having to figure out the meaning of this:
+  should_not have_at_least(#{@expected}).#{@collection_name}
+We recommend that you use this instead:
+  should have_at_most(#{@expected - 1}).#{@collection_name}
+EOF
+        end
+      end
+      
+      def description
+        "have #{relative_expectation} #{@collection_name}"
+      end
+      
+      private
+      
+      def relative_expectation
+        "#{relativities[@relativity]}#{@expected}"
+      end
+    end
+
+    # :call-seq:
+    #   should have(number).named_collection__or__sugar
+    #   should_not have(number).named_collection__or__sugar
+    #
+    # Passes if receiver is a collection with the submitted
+    # number of items OR if the receiver OWNS a collection
+    # with the submitted number of items.
+    #
+    # If the receiver OWNS the collection, you must use the name
+    # of the collection. So if a <tt>Team</tt> instance has a
+    # collection named <tt>#players</tt>, you must use that name
+    # to set the expectation.
+    #
+    # If the receiver IS the collection, you can use any name
+    # you like for <tt>named_collection</tt>. We'd recommend using
+    # either "elements", "members", or "items" as these are all
+    # standard ways of describing the things IN a collection.
+    #
+    # This also works for Strings, letting you set an expectation
+    # about its length
+    #
+    # == Examples
+    #
+    #   # Passes if team.players.size == 11
+    #   team.should have(11).players
+    #
+    #   # Passes if [1,2,3].length == 3
+    #   [1,2,3].should have(3).items #"items" is pure sugar
+    #
+    #   # Passes if "this string".length == 11
+    #   "this string".should have(11).characters #"characters" is pure sugar
+    def have(n)
+      Matchers::Have.new(n)
+    end
+    alias :have_exactly :have
+
+    # :call-seq:
+    #   should have_at_least(number).items
+    #
+    # Exactly like have() with >=.
+    #
+    # == Warning
+    #
+    # +should_not+ +have_at_least+ is not supported
+    def have_at_least(n)
+      Matchers::Have.new(n, :at_least)
+    end
+
+    # :call-seq:
+    #   should have_at_most(number).items
+    #
+    # Exactly like have() with <=.
+    #
+    # == Warning
+    #
+    # +should_not+ +have_at_most+ is not supported
+    def have_at_most(n)
+      Matchers::Have.new(n, :at_most)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/include.rb b/vendor/gems/rspec/lib/spec/matchers/include.rb
new file mode 100644
index 0000000..5476f97
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/include.rb
@@ -0,0 +1,70 @@
+module Spec
+  module Matchers
+
+    class Include #:nodoc:
+      
+      def initialize(*expecteds)
+        @expecteds = expecteds
+      end
+      
+      def matches?(actual)
+        @actual = actual
+        @expecteds.each do |expected|
+          return false unless actual.include?(expected)
+        end
+        true
+      end
+      
+      def failure_message
+        _message
+      end
+      
+      def negative_failure_message
+        _message("not ")
+      end
+      
+      def description
+        "include #{_pretty_print(@expecteds)}"
+      end
+      
+      private
+        def _message(maybe_not="")
+          "expected #{@actual.inspect} #{maybe_not}to include #{_pretty_print(@expecteds)}"
+        end
+        
+        def _pretty_print(array)
+          result = ""
+          array.each_with_index do |item, index|
+            if index < (array.length - 2)
+              result << "#{item.inspect}, "
+            elsif index < (array.length - 1)
+              result << "#{item.inspect} and "
+            else
+              result << "#{item.inspect}"
+            end
+          end
+          result
+        end
+    end
+
+    # :call-seq:
+    #   should include(expected)
+    #   should_not include(expected)
+    #
+    # Passes if actual includes expected. This works for
+    # collections and Strings. You can also pass in multiple args
+    # and it will only pass if all args are found in collection.
+    #
+    # == Examples
+    #
+    #   [1,2,3].should include(3)
+    #   [1,2,3].should include(2,3) #would pass
+    #   [1,2,3].should include(2,3,4) #would fail
+    #   [1,2,3].should_not include(4)
+    #   "spread".should include("read")
+    #   "spread".should_not include("red")
+    def include(*expected)
+      Matchers::Include.new(*expected)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/match.rb b/vendor/gems/rspec/lib/spec/matchers/match.rb
new file mode 100644
index 0000000..61ab524
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/match.rb
@@ -0,0 +1,41 @@
+module Spec
+  module Matchers
+    
+    class Match #:nodoc:
+      def initialize(expected)
+        @expected = expected
+      end
+      
+      def matches?(actual)
+        @actual = actual
+        return true if actual =~ @expected
+        return false
+      end
+      
+      def failure_message
+        return "expected #{@actual.inspect} to match #{@expected.inspect}", @expected, @actual
+      end
+      
+      def negative_failure_message
+        return "expected #{@actual.inspect} not to match #{@expected.inspect}", @expected, @actual
+      end
+      
+      def description
+        "match #{@expected.inspect}"
+      end
+    end
+    
+    # :call-seq:
+    #   should match(regexp)
+    #   should_not match(regexp)
+    #
+    # Given a Regexp, passes if actual =~ regexp
+    #
+    # == Examples
+    #
+    #   email.should match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
+    def match(regexp)
+      Matchers::Match.new(regexp)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/operator_matcher.rb b/vendor/gems/rspec/lib/spec/matchers/operator_matcher.rb
new file mode 100755
index 0000000..dd23a09
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/operator_matcher.rb
@@ -0,0 +1,73 @@
+module Spec
+  module Matchers
+    class BaseOperatorMatcher
+      attr_reader :generated_description
+      
+      def initialize(target)
+        @target = target
+      end
+
+      def ==(expected)
+        @expected = expected
+        __delegate_method_missing_to_target("==", expected)
+      end
+
+      def ===(expected)
+        @expected = expected
+        __delegate_method_missing_to_target("===", expected)
+      end
+
+      def =~(expected)
+        @expected = expected
+        __delegate_method_missing_to_target("=~", expected)
+      end
+
+      def >(expected)
+        @expected = expected
+        __delegate_method_missing_to_target(">", expected)
+      end
+
+      def >=(expected)
+        @expected = expected
+        __delegate_method_missing_to_target(">=", expected)
+      end
+
+      def <(expected)
+        @expected = expected
+        __delegate_method_missing_to_target("<", expected)
+      end
+
+      def <=(expected)
+        @expected = expected
+        __delegate_method_missing_to_target("<=", expected)
+      end
+
+      def fail_with_message(message)
+        Spec::Expectations.fail_with(message, @expected, @target)
+      end
+
+    end
+
+    class PositiveOperatorMatcher < BaseOperatorMatcher #:nodoc:
+
+      def __delegate_method_missing_to_target(operator, expected)
+        ::Spec::Matchers.generated_description = "should #{operator} #{expected.inspect}"
+        return if @target.send(operator, expected)
+        return fail_with_message("expected: #{expected.inspect},\n     got: #{@target.inspect} (using #{operator})") if ['==','===', '=~'].include?(operator)
+        return fail_with_message("expected: #{operator} #{expected.inspect},\n     got: #{operator.gsub(/./, ' ')} #{@target.inspect}")
+      end
+
+    end
+
+    class NegativeOperatorMatcher < BaseOperatorMatcher #:nodoc:
+
+      def __delegate_method_missing_to_target(operator, expected)
+        ::Spec::Matchers.generated_description = "should not #{operator} #{expected.inspect}"
+        return unless @target.send(operator, expected)
+        return fail_with_message("expected not: #{operator} #{expected.inspect},\n         got: #{operator.gsub(/./, ' ')} #{@target.inspect}")
+      end
+
+    end
+
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/raise_error.rb b/vendor/gems/rspec/lib/spec/matchers/raise_error.rb
new file mode 100644
index 0000000..65eb4dd
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/raise_error.rb
@@ -0,0 +1,109 @@
+module Spec
+  module Matchers
+    
+    class RaiseError #:nodoc:
+      def initialize(error_or_message=Exception, message=nil)
+        if String === error_or_message
+          @expected_error = Exception
+          @expected_message = error_or_message
+        else
+          @expected_error = error_or_message
+          @expected_message = message
+        end
+      end
+      
+      def matches?(proc)
+        @raised_expected_error = false
+        @raised_other = false
+        begin
+          proc.call
+        rescue @expected_error => @actual_error
+          if @expected_message.nil?
+            @raised_expected_error = true
+          else
+            verify_message
+          end
+        rescue Exception => @actual_error
+          @raised_other = true
+        ensure
+          return @raised_expected_error
+        end
+      end
+
+      def verify_message
+        case @expected_message
+        when Regexp
+          if @expected_message =~ @actual_error.message
+            @raised_expected_error = true
+          else
+            @raised_other = true
+          end
+        else
+          if @expected_message == @actual_error.message
+            @raised_expected_error = true
+          else
+            @raised_other = true
+          end
+        end
+      end
+      
+      def failure_message
+        return "expected #{expected_error}#{actual_error}" if @raised_other || !@raised_expected_error
+      end
+
+      def negative_failure_message
+        "expected no #{expected_error}#{actual_error}"
+      end
+      
+      def description
+        "raise #{expected_error}"
+      end
+      
+      private
+        def expected_error
+          case @expected_message
+          when nil
+            @expected_error
+          when Regexp
+            "#{@expected_error} with message matching #{@expected_message.inspect}"
+          else
+            "#{@expected_error} with #{@expected_message.inspect}"
+          end
+        end
+
+        def actual_error
+          @actual_error.nil? ? " but nothing was raised" : ", got #{@actual_error.inspect}"
+        end
+    end
+    
+    # :call-seq:
+    #   should raise_error()
+    #   should raise_error(NamedError)
+    #   should raise_error(NamedError, String)
+    #   should raise_error(NamedError, Regexp)
+    #   should_not raise_error()
+    #   should_not raise_error(NamedError)
+    #   should_not raise_error(NamedError, String)
+    #   should_not raise_error(NamedError, Regexp)
+    #
+    # With no args, matches if any error is raised.
+    # With a named error, matches only if that specific error is raised.
+    # With a named error and messsage specified as a String, matches only if both match.
+    # With a named error and messsage specified as a Regexp, matches only if both match.
+    #
+    # == Examples
+    #
+    #   lambda { do_something_risky }.should raise_error
+    #   lambda { do_something_risky }.should raise_error(PoorRiskDecisionError)
+    #   lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, "that was too risky")
+    #   lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, /oo ri/)
+    #
+    #   lambda { do_something_risky }.should_not raise_error
+    #   lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError)
+    #   lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, "that was too risky")
+    #   lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, /oo ri/)
+    def raise_error(error=Exception, message=nil)
+      Matchers::RaiseError.new(error, message)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/respond_to.rb b/vendor/gems/rspec/lib/spec/matchers/respond_to.rb
new file mode 100644
index 0000000..3d23422
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/respond_to.rb
@@ -0,0 +1,45 @@
+module Spec
+  module Matchers
+    
+    class RespondTo #:nodoc:
+      def initialize(*names)
+        @names = names
+        @names_not_responded_to = []
+      end
+      
+      def matches?(target)
+        @names.each do |name|
+          unless target.respond_to?(name)
+            @names_not_responded_to << name
+          end
+        end
+        return @names_not_responded_to.empty?
+      end
+      
+      def failure_message
+        "expected target to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}"
+      end
+      
+      def negative_failure_message
+        "expected target not to respond to #{@names.collect {|name| name.inspect }.join(', ')}"
+      end
+      
+      def description
+        "respond to ##{@names.to_s}"
+      end
+    end
+    
+    # :call-seq:
+    #   should respond_to(*names)
+    #   should_not respond_to(*names)
+    #
+    # Matches if the target object responds to all of the names
+    # provided. Names can be Strings or Symbols.
+    #
+    # == Examples
+    # 
+    def respond_to(*names)
+      Matchers::RespondTo.new(*names)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/satisfy.rb b/vendor/gems/rspec/lib/spec/matchers/satisfy.rb
new file mode 100644
index 0000000..6c0ca95
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/satisfy.rb
@@ -0,0 +1,47 @@
+module Spec
+  module Matchers
+    
+    class Satisfy #:nodoc:
+      def initialize(&block)
+        @block = block
+      end
+      
+      def matches?(actual, &block)
+        @block = block if block
+        @actual = actual
+        @block.call(actual)
+      end
+      
+      def failure_message
+        "expected #{@actual} to satisfy block"
+      end
+
+      def negative_failure_message
+        "expected #{@actual} not to satisfy block"
+      end
+    end
+    
+    # :call-seq:
+    #   should satisfy {}
+    #   should_not satisfy {}
+    #
+    # Passes if the submitted block returns true. Yields target to the
+    # block.
+    #
+    # Generally speaking, this should be thought of as a last resort when
+    # you can't find any other way to specify the behaviour you wish to
+    # specify.
+    #
+    # If you do find yourself in such a situation, you could always write
+    # a custom matcher, which would likely make your specs more expressive.
+    #
+    # == Examples
+    #
+    #   5.should satisfy { |n|
+    #     n > 3
+    #   }
+    def satisfy(&block)
+      Matchers::Satisfy.new(&block)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/matchers/simple_matcher.rb b/vendor/gems/rspec/lib/spec/matchers/simple_matcher.rb
new file mode 100644
index 0000000..ac547d0
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/simple_matcher.rb
@@ -0,0 +1,29 @@
+module Spec
+  module Matchers
+    class SimpleMatcher
+      attr_reader :description
+      
+      def initialize(description, &match_block)
+        @description = description
+        @match_block = match_block
+      end
+
+      def matches?(actual)
+        @actual = actual
+        return @match_block.call(@actual)
+      end
+
+      def failure_message()
+        return %[expected #{@description.inspect} but got #{@actual.inspect}]
+      end
+        
+      def negative_failure_message()
+        return %[expected not to get #{@description.inspect}, but got #{@actual.inspect}]
+      end
+    end
+    
+    def simple_matcher(message, &match_block)
+      SimpleMatcher.new(message, &match_block)
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/matchers/throw_symbol.rb b/vendor/gems/rspec/lib/spec/matchers/throw_symbol.rb
new file mode 100644
index 0000000..c74d844
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/matchers/throw_symbol.rb
@@ -0,0 +1,74 @@
+module Spec
+  module Matchers
+    
+    class ThrowSymbol #:nodoc:
+      def initialize(expected=nil)
+        @expected = expected
+        @actual = nil
+      end
+      
+      def matches?(proc)
+        begin
+          proc.call
+        rescue NameError => e
+          raise e unless e.message =~ /uncaught throw/
+          @actual = e.name.to_sym
+        ensure
+          if @expected.nil?
+            return @actual.nil? ? false : true
+          else
+            return @actual == @expected
+          end
+        end
+      end
+
+      def failure_message
+        if @actual
+          "expected #{expected}, got #{@actual.inspect}"
+        else
+          "expected #{expected} but nothing was thrown"
+        end
+      end
+      
+      def negative_failure_message
+        if @expected
+          "expected #{expected} not to be thrown"
+        else
+          "expected no Symbol, got :#{@actual}"
+        end
+      end
+      
+      def description
+        "throw #{expected}"
+      end
+      
+      private
+      
+        def expected
+          @expected.nil? ? "a Symbol" : @expected.inspect
+        end
+      
+    end
+ 
+    # :call-seq:
+    #   should throw_symbol()
+    #   should throw_symbol(:sym)
+    #   should_not throw_symbol()
+    #   should_not throw_symbol(:sym)
+    #
+    # Given a Symbol argument, matches if a proc throws the specified Symbol.
+    #
+    # Given no argument, matches if a proc throws any Symbol.
+    #
+    # == Examples
+    #
+    #   lambda { do_something_risky }.should throw_symbol
+    #   lambda { do_something_risky }.should throw_symbol(:that_was_risky)
+    #
+    #   lambda { do_something_risky }.should_not throw_symbol
+    #   lambda { do_something_risky }.should_not throw_symbol(:that_was_risky)
+    def throw_symbol(sym=nil)
+      Matchers::ThrowSymbol.new(sym)
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks.rb b/vendor/gems/rspec/lib/spec/mocks.rb
new file mode 100644
index 0000000..9f9cd21
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks.rb
@@ -0,0 +1,211 @@
+require 'spec/mocks/methods'
+require 'spec/mocks/argument_constraint_matchers'
+require 'spec/mocks/spec_methods'
+require 'spec/mocks/proxy'
+require 'spec/mocks/mock'
+require 'spec/mocks/argument_expectation'
+require 'spec/mocks/message_expectation'
+require 'spec/mocks/order_group'
+require 'spec/mocks/errors'
+require 'spec/mocks/error_generator'
+require 'spec/mocks/extensions/object'
+require 'spec/mocks/space'
+
+
+module Spec
+  # == Mocks and Stubs
+  #
+  # RSpec will create Mock Objects and Stubs for you at runtime, or attach stub/mock behaviour
+  # to any of your real objects (Partial Mock/Stub). Because the underlying implementation
+  # for mocks and stubs is the same, you can intermingle mock and stub
+  # behaviour in either dynamically generated mocks or your pre-existing classes.
+  # There is a semantic difference in how they are created, however,
+  # which can help clarify the role it is playing within a given spec.
+  #
+  # == Mock Objects
+  # 
+  # Mocks are objects that allow you to set and verify expectations that they will
+  # receive specific messages during run time. They are very useful for specifying how the subject of
+  # the spec interacts with its collaborators. This approach is widely known as "interaction
+  # testing".
+  # 
+  # Mocks are also very powerful as a design tool. As you are
+  # driving the implementation of a given class, Mocks provide an anonymous
+  # collaborator that can change in behaviour as quickly as you can write an expectation in your
+  # spec. This flexibility allows you to design the interface of a collaborator that often
+  # does not yet exist. As the shape of the class being specified becomes more clear, so do the
+  # requirements for its collaborators - often leading to the discovery of new types that are
+  # needed in your system.
+  # 
+  # Read Endo-Testing[http://www.mockobjects.com/files/endotesting.pdf] for a much
+  # more in depth description of this process.
+  # 
+  # == Stubs
+  # 
+  # Stubs are objects that allow you to set "stub" responses to
+  # messages. As Martin Fowler points out on his site,
+  # mocks_arent_stubs[http://www.martinfowler.com/articles/mocksArentStubs.html].
+  # Paraphrasing Fowler's paraphrasing
+  # of Gerard Meszaros: Stubs provide canned responses to messages they might receive in a test, while
+  # mocks allow you to specify and, subsquently, verify that certain messages should be received during
+  # the execution of a test.
+  # 
+  # == Partial Mocks/Stubs
+  # 
+  # RSpec also supports partial mocking/stubbing, allowing you to add stub/mock behaviour
+  # to instances of your existing classes. This is generally
+  # something to be avoided, because changes to the class can have ripple effects on
+  # seemingly unrelated specs. When specs fail due to these ripple effects, the fact
+  # that some methods are being mocked can make it difficult to understand why a
+  # failure is occurring.
+  # 
+  # That said, partials do allow you to expect and
+  # verify interactions with class methods such as +#find+ and +#create+
+  # on Ruby on Rails model classes.
+  # 
+  # == Further Reading
+  # 
+  # There are many different viewpoints about the meaning of mocks and stubs. If you are interested
+  # in learning more, here is some recommended reading:
+  # 
+  # * Mock Objects: http://www.mockobjects.com/
+  # * Endo-Testing: http://www.mockobjects.com/files/endotesting.pdf
+  # * Mock Roles, Not Objects: http://www.mockobjects.com/files/mockrolesnotobjects.pdf
+  # * Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html
+  # * Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html
+  #
+  # == Creating a Mock
+  #
+  # You can create a mock in any specification (or setup) using:
+  #
+  #   mock(name, options={})
+  #
+  # The optional +options+ argument is a +Hash+. Currently the only supported
+  # option is +:null_object+. Setting this to true instructs the mock to ignore
+  # any messages it hasn’t been told to expect – and quietly return itself. For example:
+  #
+  #   mock("person", :null_object => true)
+  #
+  # == Creating a Stub
+  #
+  # You can create a stub in any specification (or setup) using:
+  #
+  #   stub(name, stub_methods_and_values_hash)
+  #
+  # For example, if you wanted to create an object that always returns
+  # "More?!?!?!" to "please_sir_may_i_have_some_more" you would do this:
+  #
+  #   stub("Mr Sykes", :please_sir_may_i_have_some_more => "More?!?!?!")
+  #
+  # == Creating a Partial Mock
+  #
+  # You don't really "create" a partial mock, you simply add method stubs and/or
+  # mock expectations to existing classes and objects:
+  #
+  #   Factory.should_receive(:find).with(id).and_return(value)
+  #   obj.stub!(:to_i).and_return(3)
+  #   etc ...
+  #
+  # == Expecting Messages
+  #
+  #   my_mock.should_receive(:sym)
+  #   my_mock.should_not_receive(:sym)
+  #   
+  # == Expecting Arguments
+  #
+  #   my_mock.should_receive(:sym).with(*args)
+  #   my_mock.should_not_receive(:sym).with(*args)
+  #
+  # == Argument Constraints using Expression Matchers
+  #
+  # Arguments that are passed to #with are compared with actual arguments received
+  # using == by default. In cases in which you want to specify things about the arguments
+  # rather than the arguments themselves, you can use any of the Expression Matchers.
+  # They don't all make syntactic sense (they were primarily designed for use with
+  # Spec::Expectations), but you are free to create your own custom Spec::Matchers.
+  #
+  # Spec::Mocks does provide one additional Matcher method named #ducktype.
+  #
+  # In addition, Spec::Mocks adds some keyword Symbols that you can use to
+  # specify certain kinds of arguments:
+  #
+  #   my_mock.should_receive(:sym).with(no_args())
+  #   my_mock.should_receive(:sym).with(any_args())
+  #   my_mock.should_receive(:sym).with(1, an_instance_of(Numeric), "b") #2nd argument can any type of Numeric
+  #   my_mock.should_receive(:sym).with(1, boolean(), "b") #2nd argument can true or false
+  #   my_mock.should_receive(:sym).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp
+  #   my_mock.should_receive(:sym).with(1, anything(), "b") #2nd argument can be anything at all
+  #   my_mock.should_receive(:sym).with(1, ducktype(:abs, :div), "b")
+  #                            #2nd argument can be object that responds to #abs and #div
+  #                                                                       
+  # == Receive Counts
+  #
+  #   my_mock.should_receive(:sym).once
+  #   my_mock.should_receive(:sym).twice
+  #   my_mock.should_receive(:sym).exactly(n).times
+  #   my_mock.should_receive(:sym).at_least(:once)
+  #   my_mock.should_receive(:sym).at_least(:twice)
+  #   my_mock.should_receive(:sym).at_least(n).times
+  #   my_mock.should_receive(:sym).at_most(:once)
+  #   my_mock.should_receive(:sym).at_most(:twice)
+  #   my_mock.should_receive(:sym).at_most(n).times
+  #   my_mock.should_receive(:sym).any_number_of_times
+  #
+  # == Ordering
+  #
+  #   my_mock.should_receive(:sym).ordered
+  #   my_mock.should_receive(:other_sym).ordered
+  #     #This will fail if the messages are received out of order
+  #
+  # == Setting Reponses
+  #
+  # Whether you are setting a mock expectation or a simple stub, you can tell the
+  # object precisely how to respond:
+  #
+  #   my_mock.should_receive(:sym).and_return(value)
+  #   my_mock.should_receive(:sym).exactly(3).times.and_return(value1, value2, value3)
+  #     # returns value1 the first time, value2 the second, etc
+  #   my_mock.should_receive(:sym).and_return { ... } #returns value returned by the block
+  #   my_mock.should_receive(:sym).and_raise(error)
+  #     #error can be an instantiated object or a class
+  #     #if it is a class, it must be instantiable with no args
+  #   my_mock.should_receive(:sym).and_throw(:sym)
+  #   my_mock.should_receive(:sym).and_yield(values,to,yield)
+  #   my_mock.should_receive(:sym).and_yield(values,to,yield).and_yield(some,other,values,this,time)
+  #     # for methods that yield to a block multiple times
+  #
+  # Any of these responses can be applied to a stub as well, but stubs do
+  # not support any qualifiers about the message received (i.e. you can't specify arguments
+  # or receive counts):
+  #
+  #   my_mock.stub!(:sym).and_return(value)
+  #   my_mock.stub!(:sym).and_return(value1, value2, value3)
+  #   my_mock.stub!(:sym).and_raise(error)
+  #   my_mock.stub!(:sym).and_throw(:sym)
+  #   my_mock.stub!(:sym).and_yield(values,to,yield)
+  #   my_mock.stub!(:sym).and_yield(values,to,yield).and_yield(some,other,values,this,time)
+  #
+  # == Arbitrary Handling
+  #
+  # Once in a while you'll find that the available expectations don't solve the
+  # particular problem you are trying to solve. Imagine that you expect the message
+  # to come with an Array argument that has a specific length, but you don't care
+  # what is in it. You could do this:
+  #
+  #   my_mock.should_receive(:sym) do |arg|
+  #     arg.should be_an_istance_of(Array)
+  #     arg.length.should == 7
+  #   end
+  #
+  # Note that this would fail if the number of arguments received was different from
+  # the number of block arguments (in this case 1).
+  #
+  # == Combining Expectation Details
+  #
+  # Combining the message name with specific arguments, receive counts and responses
+  # you can get quite a bit of detail in your expectations:
+  #
+  #   my_mock.should_receive(:<<).with("illegal value").once.and_raise(ArgumentError)
+  module Mocks
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/argument_constraint_matchers.rb b/vendor/gems/rspec/lib/spec/mocks/argument_constraint_matchers.rb
new file mode 100644
index 0000000..0e47770
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/argument_constraint_matchers.rb
@@ -0,0 +1,27 @@
+module Spec
+  module Mocks
+    module ArgumentConstraintMatchers
+
+      # Shortcut for creating an instance of Spec::Mocks::DuckTypeArgConstraint
+      def duck_type(*args)
+        DuckTypeArgConstraint.new(*args)
+      end
+
+      def any_args
+        AnyArgsConstraint.new
+      end
+      
+      def anything
+        AnyArgConstraint.new(nil)
+      end
+      
+      def boolean
+        BooleanArgConstraint.new(nil)
+      end
+      
+      def no_args
+        NoArgsConstraint.new
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/argument_expectation.rb b/vendor/gems/rspec/lib/spec/mocks/argument_expectation.rb
new file mode 100644
index 0000000..34a1d4d
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/argument_expectation.rb
@@ -0,0 +1,183 @@
+module Spec
+  module Mocks
+  
+    class MatcherConstraint
+      def initialize(matcher)
+        @matcher = matcher
+      end
+      
+      def matches?(value)
+        @matcher.matches?(value)
+      end
+    end
+      
+    class LiteralArgConstraint
+      def initialize(literal)
+        @literal_value = literal
+      end
+      
+      def matches?(value)
+        @literal_value == value
+      end
+    end
+    
+    class RegexpArgConstraint
+      def initialize(regexp)
+        @regexp = regexp
+      end
+      
+      def matches?(value)
+        return value =~ @regexp unless value.is_a?(Regexp)
+        value == @regexp
+      end
+    end
+    
+    class AnyArgConstraint
+      def initialize(ignore)
+      end
+      
+      def ==(other)
+        true
+      end
+      
+      # TODO - need this?
+      def matches?(value)
+        true
+      end
+    end
+    
+    class AnyArgsConstraint
+      def description
+        "any args"
+      end
+    end
+    
+    class NoArgsConstraint
+      def description
+        "no args"
+      end
+      
+      def ==(args)
+        args == []
+      end
+    end
+    
+    class NumericArgConstraint
+      def initialize(ignore)
+      end
+      
+      def matches?(value)
+        value.is_a?(Numeric)
+      end
+    end
+    
+    class BooleanArgConstraint
+      def initialize(ignore)
+      end
+      
+      def ==(value)
+        matches?(value)
+      end
+      
+      def matches?(value)
+        return true if value.is_a?(TrueClass)
+        return true if value.is_a?(FalseClass)
+        false
+      end
+    end
+    
+    class StringArgConstraint
+      def initialize(ignore)
+      end
+      
+      def matches?(value)
+        value.is_a?(String)
+      end
+    end
+    
+    class DuckTypeArgConstraint
+      def initialize(*methods_to_respond_to)
+        @methods_to_respond_to = methods_to_respond_to
+      end
+  
+      def matches?(value)
+        @methods_to_respond_to.all? { |sym| value.respond_to?(sym) }
+      end
+      
+      def description
+        "duck_type"
+      end
+    end
+
+    class ArgumentExpectation
+      attr_reader :args
+      @@constraint_classes = Hash.new { |hash, key| LiteralArgConstraint}
+      @@constraint_classes[:anything] = AnyArgConstraint
+      @@constraint_classes[:numeric] = NumericArgConstraint
+      @@constraint_classes[:boolean] = BooleanArgConstraint
+      @@constraint_classes[:string] = StringArgConstraint
+      
+      def initialize(args)
+        @args = args
+        if [:any_args] == args
+          @expected_params = nil
+          warn_deprecated(:any_args.inspect, "any_args()")
+        elsif args.length == 1 && args[0].is_a?(AnyArgsConstraint) then @expected_params = nil
+        elsif [:no_args] == args
+          @expected_params = []
+          warn_deprecated(:no_args.inspect, "no_args()")
+        elsif args.length == 1 && args[0].is_a?(NoArgsConstraint) then @expected_params = []
+        else @expected_params = process_arg_constraints(args)
+        end
+      end
+      
+      def process_arg_constraints(constraints)
+        constraints.collect do |constraint| 
+          convert_constraint(constraint)
+        end
+      end
+      
+      def warn_deprecated(deprecated_method, instead)
+        Kernel.warn "The #{deprecated_method} constraint is deprecated. Use #{instead} instead."
+      end
+      
+      def convert_constraint(constraint)
+        if [:anything, :numeric, :boolean, :string].include?(constraint)
+          case constraint
+          when :anything
+            instead = "anything()"
+          when :boolean
+            instead = "boolean()"
+          when :numeric
+            instead = "an_instance_of(Numeric)"
+          when :string
+            instead = "an_instance_of(String)"
+          end
+          warn_deprecated(constraint.inspect, instead)
+          return @@constraint_classes[constraint].new(constraint)
+        end
+        return MatcherConstraint.new(constraint) if is_matcher?(constraint)
+        return RegexpArgConstraint.new(constraint) if constraint.is_a?(Regexp)
+        return LiteralArgConstraint.new(constraint)
+      end
+      
+      def is_matcher?(obj)
+        return obj.respond_to?(:matches?) && obj.respond_to?(:description)
+      end
+      
+      def check_args(args)
+        return true if @expected_params.nil?
+        return true if @expected_params == args
+        return constraints_match?(args)
+      end
+      
+      def constraints_match?(args)
+        return false if args.length != @expected_params.length
+        @expected_params.each_index { |i| return false unless @expected_params[i].matches?(args[i]) }
+        return true
+      end
+  
+    end
+    
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/error_generator.rb b/vendor/gems/rspec/lib/spec/mocks/error_generator.rb
new file mode 100644
index 0000000..01d8f72
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/error_generator.rb
@@ -0,0 +1,84 @@
+module Spec
+  module Mocks
+    class ErrorGenerator
+      attr_writer :opts
+      
+      def initialize(target, name)
+        @target = target
+        @name = name
+      end
+      
+      def opts
+        @opts ||= {}
+      end
+
+      def raise_unexpected_message_error(sym, *args)
+        __raise "#{intro} received unexpected message :#{sym}#{arg_message(*args)}"
+      end
+      
+      def raise_unexpected_message_args_error(expectation, *args)
+        expected_args = format_args(*expectation.expected_args)
+        actual_args = args.empty? ? "(no args)" : format_args(*args)
+        __raise "#{intro} expected #{expectation.sym.inspect} with #{expected_args} but received it with #{actual_args}"
+      end
+      
+      def raise_expectation_error(sym, expected_received_count, actual_received_count, *args)
+        __raise "#{intro} expected :#{sym}#{arg_message(*args)} #{count_message(expected_received_count)}, but received it #{count_message(actual_received_count)}"
+      end
+      
+      def raise_out_of_order_error(sym)
+        __raise "#{intro} received :#{sym} out of order"
+      end
+      
+      def raise_block_failed_error(sym, detail)
+        __raise "#{intro} received :#{sym} but passed block failed with: #{detail}"
+      end
+      
+      def raise_missing_block_error(args_to_yield)
+        __raise "#{intro} asked to yield |#{arg_list(*args_to_yield)}| but no block was passed"
+      end
+      
+      def raise_wrong_arity_error(args_to_yield, arity)
+        __raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}"
+      end
+      
+      private
+      def intro
+        @name ? "Mock '#{@name}'" : @target.inspect
+      end
+      
+      def __raise(message)
+        message = opts[:message] unless opts[:message].nil?
+        Kernel::raise(Spec::Mocks::MockExpectationError, message)
+      end
+      
+      def arg_message(*args)
+        " with " + format_args(*args)
+      end
+      
+      def format_args(*args)
+        return "(no args)" if args.empty? || args == [:no_args]
+        return "(any args)" if args == [:any_args]
+        "(" + arg_list(*args) + ")"
+      end
+
+      def arg_list(*args)
+        args.collect do |arg|
+          arg.respond_to?(:description) ? arg.description : arg.inspect
+        end.join(", ")
+      end
+      
+      def count_message(count)
+        return "at least #{pretty_print(count.abs)}" if count < 0
+        return pretty_print(count)
+      end
+
+      def pretty_print(count)
+        return "once" if count == 1
+        return "twice" if count == 2
+        return "#{count} times"
+      end
+
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/errors.rb b/vendor/gems/rspec/lib/spec/mocks/errors.rb
new file mode 100644
index 0000000..68fdfe0
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/errors.rb
@@ -0,0 +1,10 @@
+module Spec
+  module Mocks
+    class MockExpectationError < StandardError
+    end
+    
+    class AmbiguousReturnError < StandardError
+    end
+  end
+end
+
diff --git a/vendor/gems/rspec/lib/spec/mocks/extensions/object.rb b/vendor/gems/rspec/lib/spec/mocks/extensions/object.rb
new file mode 100644
index 0000000..4b75310
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/extensions/object.rb
@@ -0,0 +1,3 @@
+class Object
+  include Spec::Mocks::Methods
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/message_expectation.rb b/vendor/gems/rspec/lib/spec/mocks/message_expectation.rb
new file mode 100644
index 0000000..6bd2f1c
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/message_expectation.rb
@@ -0,0 +1,267 @@
+module Spec
+  module Mocks
+
+    class BaseExpectation
+      attr_reader :sym
+      
+      def initialize(error_generator, expectation_ordering, expected_from, sym, method_block, expected_received_count=1, opts={})
+        @error_generator = error_generator
+        @error_generator.opts = opts
+        @expected_from = expected_from
+        @sym = sym
+        @method_block = method_block
+        @return_block = nil
+        @actual_received_count = 0
+        @expected_received_count = expected_received_count
+        @args_expectation = ArgumentExpectation.new([AnyArgsConstraint.new])
+        @consecutive = false
+        @exception_to_raise = nil
+        @symbol_to_throw = nil
+        @order_group = expectation_ordering
+        @at_least = nil
+        @at_most = nil
+        @args_to_yield = []
+      end
+      
+      def expected_args
+        @args_expectation.args
+      end
+
+      def and_return(*values, &return_block)
+        Kernel::raise AmbiguousReturnError unless @method_block.nil?
+        case values.size
+          when 0 then value = nil
+          when 1 then value = values[0]
+        else
+          value = values
+          @consecutive = true
+          @expected_received_count = values.size if !ignoring_args? &&
+                                                    @expected_received_count < values.size
+        end
+        @return_block = block_given? ? return_block : lambda { value }
+        # Ruby 1.9 - see where this is used below
+        @ignore_args = !block_given?
+      end
+      
+      # :call-seq:
+      #   and_raise()
+      #   and_raise(Exception) #any exception class
+      #   and_raise(exception) #any exception object
+      #
+      # == Warning
+      #
+      # When you pass an exception class, the MessageExpectation will
+      # raise an instance of it, creating it with +new+. If the exception
+      # class initializer requires any parameters, you must pass in an
+      # instance and not the class.
+      def and_raise(exception=Exception)
+        @exception_to_raise = exception
+      end
+      
+      def and_throw(symbol)
+        @symbol_to_throw = symbol
+      end
+      
+      def and_yield(*args)
+        @args_to_yield << args
+        self
+      end
+  
+      def matches(sym, args)
+        @sym == sym and @args_expectation.check_args(args)
+      end
+      
+      def invoke(args, block)
+        @order_group.handle_order_constraint self
+
+        begin
+          Kernel::raise @exception_to_raise unless @exception_to_raise.nil?
+          Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil?
+          
+          if !@method_block.nil?
+            default_return_val = invoke_method_block(args)
+          elsif @args_to_yield.size > 0
+            default_return_val = invoke_with_yield(block)
+          else
+            default_return_val = nil
+          end
+          
+          if @consecutive
+            return invoke_consecutive_return_block(args, block)
+          elsif @return_block
+            return invoke_return_block(args, block)
+          else
+            return default_return_val
+          end
+        ensure
+          @actual_received_count += 1
+        end
+      end
+      
+      protected
+
+      def invoke_method_block(args)
+        begin
+          @method_block.call(*args)
+        rescue => detail
+          @error_generator.raise_block_failed_error @sym, detail.message
+        end
+      end
+      
+      def invoke_with_yield(block)
+        if block.nil?
+          @error_generator.raise_missing_block_error @args_to_yield
+        end
+        @args_to_yield.each do |args_to_yield_this_time|
+          if block.arity > -1 && args_to_yield_this_time.length != block.arity
+            @error_generator.raise_wrong_arity_error args_to_yield_this_time, block.arity
+          end
+          block.call(*args_to_yield_this_time)
+        end
+      end
+      
+      def invoke_consecutive_return_block(args, block)
+        args << block unless block.nil?
+        value = @return_block.call(*args)
+        
+        index = [@actual_received_count, value.size-1].min
+        value[index]
+      end
+      
+      def invoke_return_block(args, block)
+        args << block unless block.nil?
+        # Ruby 1.9 - when we set @return_block to return values
+        # regardless of arguments, any arguments will result in
+        # a "wrong number of arguments" error
+        if @ignore_args
+          @return_block.call()
+        else
+          @return_block.call(*args)
+        end
+      end
+    end
+    
+    class MessageExpectation < BaseExpectation
+      
+      def matches_name_but_not_args(sym, args)
+        @sym == sym and not @args_expectation.check_args(args)
+      end
+       
+      def verify_messages_received        
+        return if ignoring_args? || matches_exact_count? ||
+           matches_at_least_count? || matches_at_most_count?
+    
+        generate_error
+      rescue Spec::Mocks::MockExpectationError => error
+        error.backtrace.insert(0, @expected_from)
+        Kernel::raise error
+      end
+      
+      def ignoring_args?
+        @expected_received_count == :any
+      end
+      
+      def matches_at_least_count?
+        @at_least && @actual_received_count >= @expected_received_count
+      end
+      
+      def matches_at_most_count?
+        @at_most && @actual_received_count <= @expected_received_count
+      end
+      
+      def matches_exact_count?
+        @expected_received_count == @actual_received_count
+      end
+      
+      def generate_error
+        @error_generator.raise_expectation_error(@sym, @expected_received_count, @actual_received_count, *@args_expectation.args)
+      end
+
+      def with(*args, &block)
+        @method_block = block if block
+        @args_expectation = ArgumentExpectation.new(args)
+        self
+      end
+      
+      def exactly(n)
+        set_expected_received_count :exactly, n
+        self
+      end
+      
+      def at_least(n)
+        set_expected_received_count :at_least, n
+        self
+      end
+      
+      def at_most(n)
+        set_expected_received_count :at_most, n
+        self
+      end
+
+      def times(&block)
+        @method_block = block if block
+        self
+      end
+  
+      def any_number_of_times(&block)
+        @method_block = block if block
+        @expected_received_count = :any
+        self
+      end
+  
+      def never
+        @expected_received_count = 0
+        self
+      end
+  
+      def once(&block)
+        @method_block = block if block
+        @expected_received_count = 1
+        self
+      end
+  
+      def twice(&block)
+        @method_block = block if block
+        @expected_received_count = 2
+        self
+      end
+  
+      def ordered(&block)
+        @method_block = block if block
+        @order_group.register(self)
+        @ordered = true
+        self
+      end
+      
+      def negative_expectation_for?(sym)
+        return false
+      end
+      
+      protected
+        def set_expected_received_count(relativity, n)
+          @at_least = (relativity == :at_least)
+          @at_most = (relativity == :at_most)
+          @expected_received_count = case n
+            when Numeric
+              n
+            when :once
+              1
+            when :twice
+              2
+          end
+        end
+      
+    end
+    
+    class NegativeMessageExpectation < MessageExpectation
+      def initialize(message, expectation_ordering, expected_from, sym, method_block)
+        super(message, expectation_ordering, expected_from, sym, method_block, 0)
+      end
+      
+      def negative_expectation_for?(sym)
+        return @sym == sym
+      end
+    end
+    
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/methods.rb b/vendor/gems/rspec/lib/spec/mocks/methods.rb
new file mode 100644
index 0000000..d9fa324
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/methods.rb
@@ -0,0 +1,39 @@
+module Spec
+  module Mocks
+    module Methods
+      def should_receive(sym, opts={}, &block)
+        __mock_proxy.add_message_expectation(opts[:expected_from] || caller(1)[0], sym.to_sym, opts, &block)
+      end
+
+      def should_not_receive(sym, &block)
+        __mock_proxy.add_negative_message_expectation(caller(1)[0], sym.to_sym, &block)
+      end
+      
+      def stub!(sym, opts={})
+        __mock_proxy.add_stub(caller(1)[0], sym.to_sym, opts)
+      end
+      
+      def received_message?(sym, *args, &block) #:nodoc:
+        __mock_proxy.received_message?(sym.to_sym, *args, &block)
+      end
+      
+      def rspec_verify #:nodoc:
+        __mock_proxy.verify
+      end
+
+      def rspec_reset #:nodoc:
+        __mock_proxy.reset
+      end
+
+    private
+
+      def __mock_proxy
+        if Mock === self
+          @mock_proxy ||= Proxy.new(self, @name, @options)
+        else
+          @mock_proxy ||= Proxy.new(self, self.class.name)
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/mock.rb b/vendor/gems/rspec/lib/spec/mocks/mock.rb
new file mode 100644
index 0000000..f029b1b
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/mock.rb
@@ -0,0 +1,50 @@
+module Spec
+  module Mocks
+    class Mock
+      include Methods
+
+      # Creates a new mock with a +name+ (that will be used in error messages only)
+      # == Options:
+      # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving null object allowing any message to be sent to it.
+      def initialize(name, stubs_and_options={})
+        @name = name
+        @options = parse_options(stubs_and_options)
+        assign_stubs(stubs_and_options)
+      end
+      
+      # This allows for comparing the mock to other objects that proxy
+      #  such as ActiveRecords belongs_to proxy objects
+      #  By making the other object run the comparison, we're sure the call gets delegated to the proxy target
+      # This is an unfortunate side effect from ActiveRecord, but this should be safe unless the RHS redefines == in a nonsensical manner
+      def ==(other)
+        other == __mock_proxy
+      end
+
+      def method_missing(sym, *args, &block)
+        __mock_proxy.instance_eval {@messages_received << [sym, args, block]}
+        begin
+          return self if __mock_proxy.null_object?
+          super(sym, *args, &block)
+        rescue NameError
+          __mock_proxy.raise_unexpected_message_error sym, *args
+        end
+      end
+      
+      def inspect
+        "#<#{self.class}:#{sprintf '0x%x', self.object_id} @name=#{@name.inspect}>"
+      end
+      
+      private
+      
+        def parse_options(options)
+          options.has_key?(:null_object) ? {:null_object => options.delete(:null_object)} : {}
+        end
+        
+        def assign_stubs(stubs)
+          stubs.each_pair do |message, response|
+            stub!(message).and_return(response)
+          end
+        end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/order_group.rb b/vendor/gems/rspec/lib/spec/mocks/order_group.rb
new file mode 100644
index 0000000..9983207
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/order_group.rb
@@ -0,0 +1,29 @@
+module Spec
+  module Mocks
+    class OrderGroup
+      def initialize error_generator
+        @error_generator = error_generator
+        @ordering = Array.new
+      end
+      
+      def register(expectation)
+        @ordering << expectation
+      end
+      
+      def ready_for?(expectation)
+        return @ordering.first == expectation
+      end
+      
+      def consume
+        @ordering.shift
+      end
+      
+      def handle_order_constraint expectation
+        return unless @ordering.include? expectation
+        return consume if ready_for?(expectation)
+        @error_generator.raise_out_of_order_error expectation.sym
+      end
+      
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/proxy.rb b/vendor/gems/rspec/lib/spec/mocks/proxy.rb
new file mode 100644
index 0000000..03db3b1
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/proxy.rb
@@ -0,0 +1,170 @@
+module Spec
+  module Mocks
+    class Proxy
+      DEFAULT_OPTIONS = {
+        :null_object => false,
+      }
+
+      def initialize(target, name, options={})
+        @target = target
+        @name = name
+        @error_generator = ErrorGenerator.new target, name
+        @expectation_ordering = OrderGroup.new @error_generator
+        @expectations = []
+        @messages_received = []
+        @stubs = []
+        @proxied_methods = []
+        @options = options ? DEFAULT_OPTIONS.dup.merge(options) : DEFAULT_OPTIONS
+      end
+
+      def null_object?
+        @options[:null_object]
+      end
+
+      def add_message_expectation(expected_from, sym, opts={}, &block)
+        __add sym
+        @expectations << MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts)
+        @expectations.last
+      end
+
+      def add_negative_message_expectation(expected_from, sym, &block)
+        __add sym
+        @expectations << NegativeMessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil)
+        @expectations.last
+      end
+
+      def add_stub(expected_from, sym, opts={})
+        __add sym
+        @stubs.unshift MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, nil, :any, opts)
+        @stubs.first
+      end
+
+      def verify #:nodoc:
+        verify_expectations
+      ensure
+        reset
+      end
+
+      def reset
+        clear_expectations
+        clear_stubs
+        reset_proxied_methods
+        clear_proxied_methods
+      end
+
+      def received_message?(sym, *args, &block)
+        @messages_received.any? {|array| array == [sym, args, block]}
+      end
+
+      def has_negative_expectation?(sym)
+        @expectations.detect {|expectation| expectation.negative_expectation_for?(sym)}
+      end
+
+      def message_received(sym, *args, &block)
+        if expectation = find_matching_expectation(sym, *args)
+          expectation.invoke(args, block)
+        elsif stub = find_matching_method_stub(sym, *args)
+          stub.invoke([], block)
+        elsif expectation = find_almost_matching_expectation(sym, *args)
+          raise_unexpected_message_args_error(expectation, *args) unless has_negative_expectation?(sym) unless null_object?
+        else
+          @target.send :method_missing, sym, *args, &block
+        end
+      end
+
+      def raise_unexpected_message_args_error(expectation, *args)
+        @error_generator.raise_unexpected_message_args_error expectation, *args
+      end
+
+      def raise_unexpected_message_error(sym, *args)
+        @error_generator.raise_unexpected_message_error sym, *args
+      end
+      
+    private
+
+      def __add(sym)
+        $rspec_mocks.add(@target) unless $rspec_mocks.nil?
+        define_expected_method(sym)
+      end
+      
+      def define_expected_method(sym)
+        if target_responds_to?(sym) && !metaclass.method_defined?(munge(sym))
+          munged_sym = munge(sym)
+          metaclass.instance_eval do
+            alias_method munged_sym, sym if method_defined?(sym.to_s)
+          end
+          @proxied_methods << sym
+        end
+        
+        metaclass_eval(<<-EOF, __FILE__, __LINE__)
+          def #{sym}(*args, &block)
+            __mock_proxy.message_received :#{sym}, *args, &block
+          end
+        EOF
+      end
+
+      def target_responds_to?(sym)
+        return @target.send(munge(:respond_to?),sym) if @already_proxied_respond_to
+        return @already_proxied_respond_to = true if sym == :respond_to?
+        return @target.respond_to?(sym)
+      end
+
+      def munge(sym)
+        "proxied_by_rspec__#{sym.to_s}".to_sym
+      end
+
+      def clear_expectations
+        @expectations.clear
+      end
+
+      def clear_stubs
+        @stubs.clear
+      end
+
+      def clear_proxied_methods
+        @proxied_methods.clear
+      end
+
+      def metaclass_eval(str, filename, lineno)
+        metaclass.class_eval(str, filename, lineno)
+      end
+      
+      def metaclass
+        (class << @target; self; end)
+      end
+
+      def verify_expectations
+        @expectations.each do |expectation|
+          expectation.verify_messages_received
+        end
+      end
+
+      def reset_proxied_methods
+        @proxied_methods.each do |sym|
+          munged_sym = munge(sym)
+          metaclass.instance_eval do
+            if method_defined?(munged_sym.to_s)
+              alias_method sym, munged_sym
+              undef_method munged_sym
+            else
+              undef_method sym
+            end
+          end
+        end
+      end
+
+      def find_matching_expectation(sym, *args)
+        @expectations.find {|expectation| expectation.matches(sym, args)}
+      end
+
+      def find_almost_matching_expectation(sym, *args)
+        @expectations.find {|expectation| expectation.matches_name_but_not_args(sym, args)}
+      end
+
+      def find_matching_method_stub(sym, *args)
+        @stubs.find {|stub| stub.matches(sym, args)}
+      end
+
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/space.rb b/vendor/gems/rspec/lib/spec/mocks/space.rb
new file mode 100644
index 0000000..3e13224
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/space.rb
@@ -0,0 +1,28 @@
+module Spec
+  module Mocks
+    class Space
+      def add(obj)
+        mocks << obj unless mocks.detect {|m| m.equal? obj}
+      end
+
+      def verify_all
+        mocks.each do |mock|
+          mock.rspec_verify
+        end
+      end
+      
+      def reset_all
+        mocks.each do |mock|
+          mock.rspec_reset
+        end
+        mocks.clear
+      end
+      
+    private
+    
+      def mocks
+        @mocks ||= []
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/mocks/spec_methods.rb b/vendor/gems/rspec/lib/spec/mocks/spec_methods.rb
new file mode 100644
index 0000000..d92a4ce
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/mocks/spec_methods.rb
@@ -0,0 +1,38 @@
+module Spec
+  module Mocks
+    module ExampleMethods
+      include Spec::Mocks::ArgumentConstraintMatchers
+
+      # Shortcut for creating an instance of Spec::Mocks::Mock.
+      #
+      # +name+ is used for failure reporting, so you should use the
+      # role that the mock is playing in the example.
+      #
+      # +stubs_and_options+ lets you assign options and stub values
+      # at the same time. The only option available is :null_object.
+      # Anything else is treated as a stub value.
+      #
+      # == Examples
+      #
+      #   stub_thing = mock("thing", :a => "A")
+      #   stub_thing.a == "A" => true
+      #
+      #   stub_person = stub("thing", :name => "Joe", :email => "joe at domain.com")
+      #   stub_person.name => "Joe"
+      #   stub_person.email => "joe at domain.com"
+      def mock(name, stubs_and_options={})
+        Spec::Mocks::Mock.new(name, stubs_and_options)
+      end
+      
+      alias :stub :mock
+
+      # Shortcut for creating a mock object that will return itself in response
+      # to any message it receives that it hasn't been explicitly instructed
+      # to respond to.
+      def stub_everything(name = 'stub')
+        mock(name, :null_object => true)
+      end
+
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/rake/spectask.rb b/vendor/gems/rspec/lib/spec/rake/spectask.rb
new file mode 100644
index 0000000..781c151
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/rake/spectask.rb
@@ -0,0 +1,235 @@
+#!/usr/bin/env ruby
+
+# Define a task library for running RSpec contexts.
+
+require 'rake'
+require 'rake/tasklib'
+
+module Spec
+  module Rake
+
+    # A Rake task that runs a set of specs.
+    #
+    # Example:
+    #  
+    #   Spec::Rake::SpecTask.new do |t|
+    #     t.warning = true
+    #     t.rcov = true
+    #   end
+    #
+    # This will create a task that can be run with:
+    #
+    #   rake spec
+    #
+    # If rake is invoked with a "SPEC=filename" command line option,
+    # then the list of spec files will be overridden to include only the
+    # filename specified on the command line.  This provides an easy way
+    # to run just one spec.
+    #
+    # If rake is invoked with a "SPEC_OPTS=options" command line option,
+    # then the given options will override the value of the +spec_opts+
+    # attribute.
+    #
+    # If rake is invoked with a "RCOV_OPTS=options" command line option,
+    # then the given options will override the value of the +rcov_opts+
+    # attribute.
+    #
+    # Examples:
+    #
+    #   rake spec                                      # run specs normally
+    #   rake spec SPEC=just_one_file.rb                # run just one spec file.
+    #   rake spec SPEC_OPTS="--diff"                   # enable diffing
+    #   rake spec RCOV_OPTS="--aggregate myfile.txt"   # see rcov --help for details
+    #
+    # Each attribute of this task may be a proc. This allows for lazy evaluation,
+    # which is sometimes handy if you want to defer the evaluation of an attribute value
+    # until the task is run (as opposed to when it is defined).
+    #
+    # This task can also be used to run existing Test::Unit tests and get RSpec
+    # output, for example like this:
+    #
+    #   require 'rubygems'
+    #   require 'spec/rake/spectask'
+    #   Spec::Rake::SpecTask.new do |t|
+    #     t.ruby_opts = ['-rtest/unit']
+    #     t.spec_files = FileList['test/**/*_test.rb']
+    #   end
+    #
+    class SpecTask < ::Rake::TaskLib
+      class << self
+        def attr_accessor(*names)
+          super(*names)
+          names.each do |name|
+            module_eval "def #{name}() evaluate(@#{name}) end" # Allows use of procs
+          end
+        end
+      end
+
+      # Name of spec task. (default is :spec)
+      attr_accessor :name
+
+      # Array of directories to be added to $LOAD_PATH before running the
+      # specs. Defaults to ['<the absolute path to RSpec's lib directory>']
+      attr_accessor :libs
+
+      # If true, requests that the specs be run with the warning flag set.
+      # E.g. warning=true implies "ruby -w" used to run the specs. Defaults to false.
+      attr_accessor :warning
+
+      # Glob pattern to match spec files. (default is 'spec/**/*_spec.rb')
+      # Setting the SPEC environment variable overrides this.
+      attr_accessor :pattern
+
+      # Array of commandline options to pass to RSpec. Defaults to [].
+      # Setting the SPEC_OPTS environment variable overrides this.
+      attr_accessor :spec_opts
+
+      # Whether or not to use RCov (default is false)
+      # See http://eigenclass.org/hiki.rb?rcov
+      attr_accessor :rcov
+      
+      # Array of commandline options to pass to RCov. Defaults to ['--exclude', 'lib\/spec,bin\/spec'].
+      # Ignored if rcov=false
+      # Setting the RCOV_OPTS environment variable overrides this.
+      attr_accessor :rcov_opts
+
+      # Directory where the RCov report is written. Defaults to "coverage"
+      # Ignored if rcov=false
+      attr_accessor :rcov_dir
+
+      # Array of commandline options to pass to ruby. Defaults to [].
+      attr_accessor :ruby_opts
+
+      # Whether or not to fail Rake when an error occurs (typically when specs fail).
+      # Defaults to true.
+      attr_accessor :fail_on_error
+
+      # A message to print to stderr when there are failures.
+      attr_accessor :failure_message
+
+      # Where RSpec's output is written. Defaults to STDOUT.
+      # DEPRECATED. Use --format FORMAT:WHERE in spec_opts.
+      attr_accessor :out
+
+      # Explicitly define the list of spec files to be included in a
+      # spec.  +spec_files+ is expected to be an array of file names (a
+      # FileList is acceptable).  If both +pattern+ and +spec_files+ are
+      # used, then the list of spec files is the union of the two.
+      # Setting the SPEC environment variable overrides this.
+      attr_accessor :spec_files
+      
+      # Use verbose output. If this is set to true, the task will print
+      # the executed spec command to stdout. Defaults to false.
+      attr_accessor :verbose
+
+      # Defines a new task, using the name +name+.
+      def initialize(name=:spec)
+        @name = name
+        @libs = [File.expand_path(File.dirname(__FILE__) + '/../../../lib')]
+        @pattern = nil
+        @spec_files = nil
+        @spec_opts = []
+        @warning = false
+        @ruby_opts = []
+        @fail_on_error = true
+        @rcov = false
+        @rcov_opts = ['--exclude', 'lib\/spec,bin\/spec,config\/boot.rb']
+        @rcov_dir = "coverage"
+
+        yield self if block_given?
+        @pattern = 'spec/**/*_spec.rb' if pattern.nil? && spec_files.nil?
+        define
+      end
+
+      def define # :nodoc:
+        spec_script = File.expand_path(File.dirname(__FILE__) + '/../../../bin/spec')
+
+        lib_path = libs.join(File::PATH_SEPARATOR)
+        actual_name = Hash === name ? name.keys.first : name
+        unless ::Rake.application.last_comment
+          desc "Run specs" + (rcov ? " using RCov" : "")
+        end
+        task name do
+          RakeFileUtils.verbose(verbose) do
+            unless spec_file_list.empty?
+              # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts]
+              # or
+              # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts]
+              cmd = "ruby "
+
+              rb_opts = ruby_opts.clone
+              rb_opts << "-I\"#{lib_path}\""
+              rb_opts << "-S rcov" if rcov
+              rb_opts << "-w" if warning
+              cmd << rb_opts.join(" ")
+              cmd << " "
+              cmd << rcov_option_list
+              cmd << %[ -o "#{rcov_dir}" ] if rcov
+              #cmd << %Q|"#{spec_script}"|
+              cmd << " "
+              cmd << "-- " if rcov
+              cmd << spec_file_list.collect { |fn| %["#{fn}"] }.join(' ')
+              cmd << " "
+              cmd << spec_option_list
+              if out
+                cmd << " "
+                cmd << %Q| > "#{out}"|
+                STDERR.puts "The Spec::Rake::SpecTask#out attribute is DEPRECATED and will be removed in a future version. Use --format FORMAT:WHERE instead."
+              end
+              if verbose
+                puts cmd
+              end
+              unless system(cmd)
+                STDERR.puts failure_message if failure_message
+                raise("Command #{cmd} failed") if fail_on_error
+              end
+            end
+          end
+        end
+
+        if rcov
+          desc "Remove rcov products for #{actual_name}"
+          task paste("clobber_", actual_name) do
+            rm_r rcov_dir rescue nil
+          end
+
+          clobber_task = paste("clobber_", actual_name)
+          task :clobber => [clobber_task]
+
+          task actual_name => clobber_task
+        end
+        self
+      end
+
+      def rcov_option_list # :nodoc:
+        return "" unless rcov
+        ENV['RCOV_OPTS'] || rcov_opts.join(" ") || ""
+      end
+
+      def spec_option_list # :nodoc:
+        STDERR.puts "RSPECOPTS is DEPRECATED and will be removed in a future version. Use SPEC_OPTS instead." if ENV['RSPECOPTS']
+        ENV['SPEC_OPTS'] || ENV['RSPECOPTS'] || spec_opts.join(" ") || ""
+      end
+      
+      def evaluate(o) # :nodoc:
+        case o
+          when Proc then o.call
+          else o
+        end
+      end
+
+      def spec_file_list # :nodoc:
+        if ENV['SPEC']
+          FileList[ ENV['SPEC'] ]
+        else
+          result = []
+          result += spec_files.to_a if spec_files
+          result += FileList[ pattern ].to_a if pattern
+          FileList[result]
+        end
+      end
+
+    end
+  end
+end
+
diff --git a/vendor/gems/rspec/lib/spec/rake/verify_rcov.rb b/vendor/gems/rspec/lib/spec/rake/verify_rcov.rb
new file mode 100644
index 0000000..3328f9e
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/rake/verify_rcov.rb
@@ -0,0 +1,52 @@
+module RCov
+  # A task that can verify that the RCov coverage doesn't
+  # drop below a certain threshold. It should be run after
+  # running Spec::Rake::SpecTask.
+  class VerifyTask < Rake::TaskLib
+    # Name of the task. Defaults to :verify_rcov
+    attr_accessor :name
+    
+    # Path to the index.html file generated by RCov, which
+    # is the file containing the total coverage.
+    # Defaults to 'coverage/index.html'
+    attr_accessor :index_html
+    
+    # Whether or not to output details. Defaults to true.
+    attr_accessor :verbose
+    
+    # The threshold value (in percent) for coverage. If the 
+    # actual coverage is not equal to this value, the task will raise an 
+    # exception. 
+    attr_accessor :threshold
+    
+    # Require the threshold value be met exactly.  This is the default.
+    attr_accessor :require_exact_threshold
+    
+    def initialize(name=:verify_rcov)
+      @name = name
+      @index_html = 'coverage/index.html'
+      @verbose = true
+      @require_exact_threshold = true
+      yield self if block_given?
+      raise "Threshold must be set" if @threshold.nil?
+      define
+    end
+    
+    def define
+      desc "Verify that rcov coverage is at least #{threshold}%"
+      task @name do
+        total_coverage = nil
+
+        File.open(index_html).each_line do |line|
+          if line =~ /<tt class='coverage_total'>(\d+\.\d+)%<\/tt>/
+            total_coverage = eval($1)
+            break
+          end
+        end
+        puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose
+        raise "Coverage must be at least #{threshold}% but was #{total_coverage}%" if total_coverage < threshold
+        raise "Coverage has increased above the threshold of #{threshold}% to #{total_coverage}%. You should update your threshold value." if (total_coverage > threshold) and require_exact_threshold
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner.rb b/vendor/gems/rspec/lib/spec/runner.rb
new file mode 100644
index 0000000..97ef95b
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner.rb
@@ -0,0 +1,202 @@
+require 'spec/runner/options'
+require 'spec/runner/option_parser'
+require 'spec/runner/example_group_runner'
+require 'spec/runner/command_line'
+require 'spec/runner/drb_command_line'
+require 'spec/runner/backtrace_tweaker'
+require 'spec/runner/reporter'
+require 'spec/runner/spec_parser'
+require 'spec/runner/class_and_arguments_parser'
+
+module Spec
+  # == ExampleGroups and Examples
+  # 
+  # Rather than expressing examples in classes, RSpec uses a custom DSLL (DSL light) to 
+  # describe groups of examples.
+  # 
+  # A ExampleGroup is the equivalent of a fixture in xUnit-speak. It is a metaphor for the context
+  # in which you will run your executable example - a set of known objects in a known starting state.
+  # We begin be describing
+  # 
+  #   describe Account do
+  # 
+  #     before do
+  #       @account = Account.new
+  #     end
+  # 
+  #     it "should have a balance of $0" do
+  #       @account.balance.should == Money.new(0, :dollars)
+  #     end
+  # 
+  #   end
+  # 
+  # We use the before block to set up the Example (given), and then the #it method to
+  # hold the example code that expresses the event (when) and the expected outcome (then).
+  # 
+  # == Helper Methods
+  # 
+  # A primary goal of RSpec is to keep the examples clear. We therefore prefer
+  # less indirection than you might see in xUnit examples and in well factored, DRY production code. We feel
+  # that duplication is OK if removing it makes it harder to understand an example without
+  # having to look elsewhere to understand its context.
+  # 
+  # That said, RSpec does support some level of encapsulating common code in helper
+  # methods that can exist within a context or within an included module.
+  # 
+  # == Setup and Teardown
+  # 
+  # You can use before and after within a Example. Both methods take an optional
+  # scope argument so you can run the block before :each example or before :all examples
+  # 
+  #   describe "..." do
+  #     before :all do
+  #       ...
+  #     end
+  # 
+  #     before :each do
+  #       ...
+  #     end
+  # 
+  #     it "should do something" do
+  #       ...
+  #     end
+  # 
+  #     it "should do something else" do
+  #       ...
+  #     end
+  # 
+  #     after :each do
+  #       ...
+  #     end
+  # 
+  #     after :all do
+  #       ...
+  #     end
+  # 
+  #   end
+  # 
+  # The <tt>before :each</tt> block will run before each of the examples, once for each example. Likewise,
+  # the <tt>after :each</tt> block will run after each of the examples.
+  # 
+  # It is also possible to specify a <tt>before :all</tt> and <tt>after :all</tt>
+  # block that will run only once for each behaviour, respectively before the first <code>before :each</code>
+  # and after the last <code>after :each</code>. The use of these is generally discouraged, because it
+  # introduces dependencies between the examples. Still, it might prove useful for very expensive operations
+  # if you know what you are doing.
+  # 
+  # == Local helper methods
+  # 
+  # You can include local helper methods by simply expressing them within a context:
+  # 
+  #   describe "..." do
+  #   
+  #     it "..." do
+  #       helper_method
+  #     end
+  # 
+  #     def helper_method
+  #       ...
+  #     end
+  # 
+  #   end
+  # 
+  # == Included helper methods
+  # 
+  # You can include helper methods in multiple contexts by expressing them within
+  # a module, and then including that module in your context:
+  # 
+  #   module AccountExampleHelperMethods
+  #     def helper_method
+  #       ...
+  #     end
+  #   end
+  # 
+  #   describe "A new account" do
+  #     include AccountExampleHelperMethods
+  #     before do
+  #       @account = Account.new
+  #     end
+  # 
+  #     it "should have a balance of $0" do
+  #       helper_method
+  #       @account.balance.should eql(Money.new(0, :dollars))
+  #     end
+  #   end
+  # 
+  # == Shared Example Groups
+  # 
+  # You can define a shared Example Group, that may be used on other groups
+  #
+  #  share_examples_for "All Editions" do
+  #    it "all editions behaviour" ...
+  #  end
+  #
+  #  describe SmallEdition do
+  #    it_should_behave_like "All Editions"
+  #  
+  #    it "should do small edition stuff" do
+  #      ...
+  #    end
+  #  end
+  #
+  # You can also assign the shared group to a module and include that
+  #
+  #  share_as :AllEditions do
+  #    it "should do all editions stuff" ...
+  #  end
+  #
+  #  describe SmallEdition do
+  #    it_should_behave_like AllEditions
+  #  
+  #    it "should do small edition stuff" do
+  #      ...
+  #    end
+  #  end
+  #
+  # And, for those of you who prefer to use something more like Ruby, you
+  # can just include the module directly
+  #
+  #  describe SmallEdition do
+  #    include AllEditions
+  #  
+  #    it "should do small edition stuff" do
+  #      ...
+  #    end
+  #  end
+  module Runner
+    class << self
+      def configuration # :nodoc:
+        @configuration ||= Spec::Example::Configuration.new
+      end
+      
+      # Use this to configure various configurable aspects of
+      # RSpec:
+      #
+      #   Spec::Runner.configure do |configuration|
+      #     # Configure RSpec here
+      #   end
+      #
+      # The yielded <tt>configuration</tt> object is a
+      # Spec::Example::Configuration instance. See its RDoc
+      # for details about what you can do with it.
+      #
+      def configure
+        yield configuration
+      end
+      
+      def register_at_exit_hook # :nodoc:
+        $spec_runner_at_exit_hook_registered ||= nil
+        unless $spec_runner_at_exit_hook_registered
+          at_exit do
+            unless $! || Spec.run?; \
+              success = Spec.run; \
+              exit success if Spec.exit?; \
+            end
+          end
+          $spec_runner_at_exit_hook_registered = true
+        end
+      end
+      
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/backtrace_tweaker.rb b/vendor/gems/rspec/lib/spec/runner/backtrace_tweaker.rb
new file mode 100644
index 0000000..5fd2fb9
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/backtrace_tweaker.rb
@@ -0,0 +1,57 @@
+module Spec
+  module Runner
+    class BacktraceTweaker
+      def clean_up_double_slashes(line)
+        line.gsub!('//','/')
+      end
+    end
+
+    class NoisyBacktraceTweaker < BacktraceTweaker
+      def tweak_backtrace(error)
+        return if error.backtrace.nil?
+        error.backtrace.each do |line|
+          clean_up_double_slashes(line)
+        end
+      end
+    end
+
+    # Tweaks raised Exceptions to mask noisy (unneeded) parts of the backtrace
+    class QuietBacktraceTweaker < BacktraceTweaker
+      unless defined?(IGNORE_PATTERNS)
+        root_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', '..'))
+        spec_files = Dir["#{root_dir}/lib/*"].map do |path| 
+          subpath = path[root_dir.length..-1]
+          /#{subpath}/
+        end
+        IGNORE_PATTERNS = spec_files + [
+          /\/lib\/ruby\//,
+          /bin\/spec:/,
+          /bin\/rcov:/,
+          /lib\/rspec_on_rails/,
+          /vendor\/rails/,
+          # TextMate's Ruby and RSpec plugins
+          /Ruby\.tmbundle\/Support\/tmruby.rb:/,
+          /RSpec\.tmbundle\/Support\/lib/,
+          /temp_textmate\./,
+          /mock_frameworks\/rspec/,
+          /spec_server/
+        ]
+      end
+      
+      def tweak_backtrace(error)
+        return if error.backtrace.nil?
+        error.backtrace.collect! do |line|
+          clean_up_double_slashes(line)
+          IGNORE_PATTERNS.each do |ignore|
+            if line =~ ignore
+              line = nil
+              break
+            end
+          end
+          line
+        end
+        error.backtrace.compact!
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/class_and_arguments_parser.rb b/vendor/gems/rspec/lib/spec/runner/class_and_arguments_parser.rb
new file mode 100644
index 0000000..65dc451
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/class_and_arguments_parser.rb
@@ -0,0 +1,16 @@
+module Spec
+  module Runner
+    class ClassAndArgumentsParser
+      class << self
+        def parse(s)
+          if s =~ /([a-zA-Z_]+(?:::[a-zA-Z_]+)*):?(.*)/
+            arg = $2 == "" ? nil : $2
+            [$1, arg]
+          else
+            raise "Couldn't parse #{s.inspect}"
+          end
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/runner/command_line.rb b/vendor/gems/rspec/lib/spec/runner/command_line.rb
new file mode 100644
index 0000000..9849c48
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/command_line.rb
@@ -0,0 +1,28 @@
+require 'spec/runner/option_parser'
+
+module Spec
+  module Runner
+    # Facade to run specs without having to fork a new ruby process (using `spec ...`)
+    class CommandLine
+      class << self
+        # Runs specs. +argv+ is the commandline args as per the spec commandline API, +err+
+        # and +out+ are the streams output will be written to.
+        def run(instance_rspec_options)
+          # NOTE - this call to init_rspec_options is not spec'd, but neither is any of this
+          # swapping of $rspec_options. That is all here to enable rspec to run against itself
+          # and maintain coverage in a single process. Therefore, DO NOT mess with this stuff
+          # unless you know what you are doing!
+          init_rspec_options(instance_rspec_options)
+          orig_rspec_options = rspec_options
+          begin
+            $rspec_options = instance_rspec_options
+            return $rspec_options.run_examples
+          ensure
+            ::Spec.run = true
+            $rspec_options = orig_rspec_options
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/drb_command_line.rb b/vendor/gems/rspec/lib/spec/runner/drb_command_line.rb
new file mode 100644
index 0000000..6c340cf
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/drb_command_line.rb
@@ -0,0 +1,20 @@
+require "drb/drb"
+
+module Spec
+  module Runner
+    # Facade to run specs by connecting to a DRB server
+    class DrbCommandLine
+      # Runs specs on a DRB server. Note that this API is similar to that of
+      # CommandLine - making it possible for clients to use both interchangeably.
+      def self.run(options)
+        begin
+          DRb.start_service
+          spec_server = DRbObject.new_with_uri("druby://localhost:8989")
+          spec_server.run(options.argv, options.error_stream, options.output_stream)
+        rescue DRb::DRbConnError => e
+          options.error_stream.puts "No server is running"
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/example_group_runner.rb b/vendor/gems/rspec/lib/spec/runner/example_group_runner.rb
new file mode 100644
index 0000000..7275c6a
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/example_group_runner.rb
@@ -0,0 +1,59 @@
+module Spec
+  module Runner
+    class ExampleGroupRunner
+      def initialize(options)
+        @options = options
+      end
+
+      def load_files(files)
+        # It's important that loading files (or choosing not to) stays the
+        # responsibility of the ExampleGroupRunner. Some implementations (like)
+        # the one using DRb may choose *not* to load files, but instead tell
+        # someone else to do it over the wire.
+        files.each do |file|
+          load file
+        end
+      end
+
+      def run
+        prepare
+        success = true
+        example_groups.each do |example_group|
+          success = success & example_group.run
+        end
+        return success
+      ensure
+        finish
+      end
+
+      protected
+      def prepare
+        reporter.start(number_of_examples)
+        example_groups.reverse! if reverse
+      end
+
+      def finish
+        reporter.end
+        reporter.dump
+      end
+
+      def reporter
+        @options.reporter
+      end
+
+      def reverse
+        @options.reverse
+      end
+
+      def example_groups
+        @options.example_groups
+      end
+
+      def number_of_examples
+        @options.number_of_examples
+      end
+    end
+    # TODO: BT - Deprecate BehaviourRunner?
+    BehaviourRunner = ExampleGroupRunner
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/base_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/base_formatter.rb
new file mode 100644
index 0000000..c8647cf
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/base_formatter.rb
@@ -0,0 +1,78 @@
+module Spec
+  module Runner
+    module Formatter
+      # Baseclass for formatters that implements all required methods as no-ops. 
+      class BaseFormatter
+        attr_accessor :example_group, :options, :where
+        def initialize(options, where)
+          @options = options
+          @where = where
+        end
+        
+        # This method is invoked before any examples are run, right after
+        # they have all been collected. This can be useful for special
+        # formatters that need to provide progress on feedback (graphical ones)
+        #
+        # This method will only be invoked once, and the next one to be invoked
+        # is #add_example_group
+        def start(example_count)
+        end
+
+        # This method is invoked at the beginning of the execution of each example_group.
+        # +name+ is the name of the example_group and +first+ is true if it is the
+        # first example_group - otherwise it's false.
+        #
+        # The next method to be invoked after this is #example_failed or #example_finished
+        def add_example_group(example_group)
+          @example_group = example_group
+        end
+
+        # This method is invoked when an +example+ starts.
+        def example_started(example)
+        end
+
+        # This method is invoked when an +example+ passes.
+        def example_passed(example)
+        end
+
+        # This method is invoked when an +example+ fails, i.e. an exception occurred
+        # inside it (such as a failed should or other exception). +counter+ is the 
+        # sequence number of the failure (starting at 1) and +failure+ is the associated 
+        # Failure object.
+        def example_failed(example, counter, failure)
+        end
+        
+        # This method is invoked when an example is not yet implemented (i.e. has not
+        # been provided a block), or when an ExamplePendingError is raised.
+        # +message+ is the message from the ExamplePendingError, if it exists, or the
+        # default value of "Not Yet Implemented"
+        def example_pending(example_group_description, example, message)
+        end
+
+        # This method is invoked after all of the examples have executed. The next method
+        # to be invoked after this one is #dump_failure (once for each failed example),
+        def start_dump
+        end
+
+        # Dumps detailed information about an example failure.
+        # This method is invoked for each failed example after all examples have run. +counter+ is the sequence number
+        # of the associated example. +failure+ is a Failure object, which contains detailed
+        # information about the failure.
+        def dump_failure(counter, failure)
+        end
+      
+        # This method is invoked after the dumping of examples and failures.
+        def dump_summary(duration, example_count, failure_count, pending_count)
+        end
+        
+        # This gets invoked after the summary if option is set to do so.
+        def dump_pending
+        end
+
+        # This method is invoked at the very end. Allows the formatter to clean up, like closing open streams.
+        def close
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/base_text_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/base_text_formatter.rb
new file mode 100644
index 0000000..859b264
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/base_text_formatter.rb
@@ -0,0 +1,130 @@
+require 'spec/runner/formatter/base_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      # Baseclass for text-based formatters. Can in fact be used for
+      # non-text based ones too - just ignore the +output+ constructor
+      # argument.
+      class BaseTextFormatter < BaseFormatter
+        attr_reader :output, :pending_examples
+        # Creates a new instance that will write to +where+. If +where+ is a
+        # String, output will be written to the File with that name, otherwise
+        # +where+ is exected to be an IO (or an object that responds to #puts and #write).
+        def initialize(options, where)
+          super
+          if where.is_a?(String)
+            @output = File.open(where, 'w')
+          elsif where == STDOUT
+            @output = Kernel
+            def @output.flush
+              STDOUT.flush
+            end
+          else
+            @output = where
+          end
+          @pending_examples = []
+        end
+        
+        def example_pending(example_group_description, example, message)
+          @pending_examples << ["#{example_group_description} #{example.description}", message]
+        end
+        
+        def dump_failure(counter, failure)
+          @output.puts
+          @output.puts "#{counter.to_s})"
+          @output.puts colourise("#{failure.header}\n#{failure.exception.message}", failure)
+          @output.puts format_backtrace(failure.exception.backtrace)
+          @output.flush
+        end
+        
+        def colourise(s, failure)
+          if(failure.expectation_not_met?)
+            red(s)
+          elsif(failure.pending_fixed?)
+            blue(s)
+          else
+            magenta(s)
+          end
+        end
+      
+        def dump_summary(duration, example_count, failure_count, pending_count)
+          return if dry_run?
+          @output.puts
+          @output.puts "Finished in #{duration} seconds"
+          @output.puts
+
+          summary = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
+          summary << ", #{pending_count} pending" if pending_count > 0  
+
+          if failure_count == 0
+            if pending_count > 0
+              @output.puts yellow(summary)
+            else
+              @output.puts green(summary)
+            end
+          else
+            @output.puts red(summary)
+          end
+          @output.flush
+        end
+
+        def dump_pending
+          unless @pending_examples.empty?
+            @output.puts
+            @output.puts "Pending:"
+            @pending_examples.each do |pending_example|
+              @output.puts "#{pending_example[0]} (#{pending_example[1]})" 
+            end
+          end
+          @output.flush
+        end
+        
+        def close
+          if IO === @output
+            @output.close 
+          end
+        end
+        
+        def format_backtrace(backtrace)
+          return "" if backtrace.nil?
+          backtrace.map { |line| backtrace_line(line) }.join("\n")
+        end
+      
+      protected
+
+        def colour?
+          @options.colour ? true : false
+        end
+
+        def dry_run?
+          @options.dry_run ? true : false
+        end
+        
+        def backtrace_line(line)
+          line.sub(/\A([^:]+:\d+)$/, '\\1:')
+        end
+
+        def colour(text, colour_code)
+          return text unless colour? && output_to_tty?
+          "#{colour_code}#{text}\e[0m"
+        end
+
+        def output_to_tty?
+          begin
+            @output == Kernel || @output.tty?
+          rescue NoMethodError
+            false
+          end
+        end
+        
+        def green(text); colour(text, "\e[32m"); end
+        def red(text); colour(text, "\e[31m"); end
+        def magenta(text); colour(text, "\e[35m"); end
+        def yellow(text); colour(text, "\e[33m"); end
+        def blue(text); colour(text, "\e[34m"); end
+        
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb
new file mode 100644
index 0000000..5a46079
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb
@@ -0,0 +1,31 @@
+require 'spec/runner/formatter/base_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      class FailingExampleGroupsFormatter < BaseTextFormatter
+        def add_example_group(example_group)
+          super
+          @example_group_description_parts = example_group.description_parts
+        end
+
+        def example_failed(example, counter, failure)
+          if @example_group_description_parts
+            description_parts = @example_group_description_parts.collect do |description|
+              description =~ /(.*) \(druby.*\)$/ ? $1 : description
+            end
+            @output.puts ::Spec::Example::ExampleGroupMethods.description_text(*description_parts)
+            @output.flush
+            @example_group_description_parts = nil
+          end
+        end
+
+        def dump_failure(counter, failure)
+        end
+
+        def dump_summary(duration, example_count, failure_count, pending_count)
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/failing_examples_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/failing_examples_formatter.rb
new file mode 100644
index 0000000..e3a271c
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/failing_examples_formatter.rb
@@ -0,0 +1,20 @@
+require 'spec/runner/formatter/base_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      class FailingExamplesFormatter < BaseTextFormatter      
+        def example_failed(example, counter, failure)
+          @output.puts "#{example_group.description} #{example.description}"
+          @output.flush
+        end
+
+        def dump_failure(counter, failure)
+        end
+
+        def dump_summary(duration, example_count, failure_count, pending_count)
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/html_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/html_formatter.rb
new file mode 100644
index 0000000..ad153c8
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/html_formatter.rb
@@ -0,0 +1,333 @@
+require 'erb'
+require 'spec/runner/formatter/base_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      class HtmlFormatter < BaseTextFormatter
+        include ERB::Util # for the #h method
+        
+        def initialize(options, output)
+          super
+          @current_example_group_number = 0
+          @current_example_number = 0
+        end
+
+        # The number of the currently running example_group
+        def current_example_group_number
+          @current_example_group_number
+        end
+        
+        # The number of the currently running example (a global counter)
+        def current_example_number
+          @current_example_number
+        end
+        
+        def start(example_count)
+          @example_count = example_count
+
+          @output.puts html_header
+          @output.puts report_header
+          @output.flush
+        end
+
+        def add_example_group(example_group)
+          super
+          @example_group_red = false
+          @example_group_red = false
+          @current_example_group_number += 1
+          unless current_example_group_number == 1
+            @output.puts "  </dl>"
+            @output.puts "</div>"
+          end
+          @output.puts "<div class=\"example_group\">"
+          @output.puts "  <dl>"
+          @output.puts "  <dt id=\"example_group_#{current_example_group_number}\">#{h(example_group.description)}</dt>"
+          @output.flush
+        end
+
+        def start_dump
+          @output.puts "  </dl>"
+          @output.puts "</div>"
+          @output.flush
+        end
+
+        def example_started(example)
+          @current_example_number += 1
+        end
+
+        def example_passed(example)
+          move_progress
+          @output.puts "    <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{h(example.description)}</span></dd>"
+          @output.flush
+        end
+
+        def example_failed(example, counter, failure)
+          extra = extra_failure_content(failure)
+          failure_style = failure.pending_fixed? ? 'pending_fixed' : 'failed'
+          @output.puts "    <script type=\"text/javascript\">makeRed('rspec-header');</script>" unless @header_red
+          @header_red = true
+          @output.puts "    <script type=\"text/javascript\">makeRed('example_group_#{current_example_group_number}');</script>" unless @example_group_red
+          @example_group_red = true
+          move_progress
+          @output.puts "    <dd class=\"spec #{failure_style}\">"
+          @output.puts "      <span class=\"failed_spec_name\">#{h(example.description)}</span>"
+          @output.puts "      <div class=\"failure\" id=\"failure_#{counter}\">"
+          @output.puts "        <div class=\"message\"><pre>#{h(failure.exception.message)}</pre></div>" unless failure.exception.nil?
+          @output.puts "        <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil?
+          @output.puts extra unless extra == ""
+          @output.puts "      </div>"
+          @output.puts "    </dd>"
+          @output.flush
+        end
+
+        def example_pending(example_group_description, example, message)
+          @output.puts "    <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red
+          @output.puts "    <script type=\"text/javascript\">makeYellow('example_group_#{current_example_group_number}');</script>" unless @example_group_red
+          move_progress
+          @output.puts "    <dd class=\"spec not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example.description)} (PENDING: #{h(message)})</span></dd>"
+          @output.flush
+        end
+
+        # Override this method if you wish to output extra HTML for a failed spec. For example, you
+        # could output links to images or other files produced during the specs.
+        #
+        def extra_failure_content(failure)
+          require 'spec/runner/formatter/snippet_extractor'
+          @snippet_extractor ||= SnippetExtractor.new
+          "    <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(failure.exception)}</code></pre>"
+        end
+        
+        def move_progress
+          @output.puts "    <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
+          @output.flush
+        end
+
+        def percent_done
+          result = 100.0
+          if @example_count != 0
+            result = ((current_example_number).to_f / @example_count.to_f * 1000).to_i / 10.0
+          end
+          result
+        end
+
+        def dump_failure(counter, failure)
+        end
+
+        def dump_summary(duration, example_count, failure_count, pending_count)
+          if dry_run?
+            totals = "This was a dry-run"
+          else
+            totals = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
+            totals << ", #{pending_count} pending" if pending_count > 0  
+          end
+          @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>"
+          @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
+          @output.puts "</div>"
+          @output.puts "</div>"
+          @output.puts "</body>"
+          @output.puts "</html>"
+          @output.flush
+        end
+
+        def html_header 
+          <<-EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+EOF
+        end
+
+        def report_header
+          <<-EOF
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+#{global_scripts}
+    // ]]>
+  </script>
+  <style type="text/css">
+#{global_styles}
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+EOF
+        end
+
+        def global_scripts
+          <<-EOF
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+EOF
+        end
+        
+        def global_styles
+          <<-EOF
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+EOF
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/profile_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/profile_formatter.rb
new file mode 100644
index 0000000..3784f3a
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/profile_formatter.rb
@@ -0,0 +1,47 @@
+require 'spec/runner/formatter/progress_bar_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      class ProfileFormatter < ProgressBarFormatter
+        
+        def initialize(options, where)
+          super
+          @example_times = []
+        end
+        
+        def start(count)
+          @output.puts "Profiling enabled."
+        end
+        
+        def example_started(example)
+          @time = Time.now
+        end
+        
+        def example_passed(example)
+          super
+          @example_times << [
+            example_group.description,
+            example.description,
+            Time.now - @time
+          ]
+        end
+        
+        def start_dump
+          super
+          @output.puts "\n\nTop 10 slowest examples:\n"
+          
+          @example_times = @example_times.sort_by do |description, example, time|
+            time
+          end.reverse
+          
+          @example_times[0..9].each do |description, example, time|
+            @output.print red(sprintf("%.7f", time))
+            @output.puts " #{description} #{example}"
+          end
+          @output.flush
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb
new file mode 100644
index 0000000..8d0e504
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb
@@ -0,0 +1,30 @@
+require 'spec/runner/formatter/base_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      class ProgressBarFormatter < BaseTextFormatter
+        def example_failed(example, counter, failure)
+          @output.print colourise('F', failure)
+          @output.flush
+        end
+
+        def example_passed(example)
+          @output.print green('.')
+          @output.flush
+        end
+      
+        def example_pending(example_group_description, example, message)
+          super
+          @output.print yellow('P')
+          @output.flush
+        end
+        
+        def start_dump
+          @output.puts
+          @output.flush
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/snippet_extractor.rb b/vendor/gems/rspec/lib/spec/runner/formatter/snippet_extractor.rb
new file mode 100644
index 0000000..41119fe
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/snippet_extractor.rb
@@ -0,0 +1,52 @@
+module Spec
+  module Runner
+    module Formatter
+      # This class extracts code snippets by looking at the backtrace of the passed error
+      class SnippetExtractor #:nodoc:
+        class NullConverter; def convert(code, pre); code; end; end #:nodoc:
+        begin; require 'rubygems'; require 'syntax/convertors/html'; @@converter = Syntax::Convertors::HTML.for_syntax "ruby"; rescue LoadError => e; @@converter = NullConverter.new; end
+        
+        def snippet(error)
+          raw_code, line = snippet_for(error.backtrace[0])
+          highlighted = @@converter.convert(raw_code, false)
+          highlighted << "\n<span class=\"comment\"># gem install syntax to get syntax highlighting</span>" if @@converter.is_a?(NullConverter)
+          post_process(highlighted, line)
+        end
+        
+        def snippet_for(error_line)
+          if error_line =~ /(.*):(\d+)/
+            file = $1
+            line = $2.to_i
+            [lines_around(file, line), line]
+          else
+            ["# Couldn't get snippet for #{error_line}", 1]
+          end
+        end
+        
+        def lines_around(file, line)
+          if File.file?(file)
+            lines = File.open(file).read.split("\n")
+            min = [0, line-3].max
+            max = [line+1, lines.length-1].min
+            selected_lines = []
+            selected_lines.join("\n")
+            lines[min..max].join("\n")
+          else
+            "# Couldn't get snippet for #{file}"
+          end
+        end
+        
+        def post_process(highlighted, offending_line)
+          new_lines = []
+          highlighted.split("\n").each_with_index do |line, i|
+            new_line = "<span class=\"linenum\">#{offending_line+i-2}</span>#{line}"
+            new_line = "<span class=\"offending\">#{new_line}</span>" if i == 2
+            new_lines << new_line
+          end
+          new_lines.join("\n")
+        end
+        
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/specdoc_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/specdoc_formatter.rb
new file mode 100644
index 0000000..f426dc9
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/specdoc_formatter.rb
@@ -0,0 +1,39 @@
+require 'spec/runner/formatter/base_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      class SpecdocFormatter < BaseTextFormatter
+        def add_example_group(example_group)
+          super
+          output.puts
+          output.puts example_group.description
+          output.flush
+        end
+      
+        def example_failed(example, counter, failure)
+          message = if failure.expectation_not_met?
+            "- #{example.description} (FAILED - #{counter})"
+          else
+            "- #{example.description} (ERROR - #{counter})"
+          end
+          
+          output.puts(failure.expectation_not_met? ? red(message) : magenta(message))
+          output.flush
+        end
+        
+        def example_passed(example)
+          message = "- #{example.description}"
+          output.puts green(message)
+          output.flush
+        end
+        
+        def example_pending(example_group_description, example, message)
+          super
+          output.puts yellow("- #{example.description} (PENDING: #{message})")
+          output.flush
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/story/html_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/story/html_formatter.rb
new file mode 100644
index 0000000..5a81346
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/story/html_formatter.rb
@@ -0,0 +1,128 @@
+require 'erb'
+require 'spec/runner/formatter/base_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      module Story
+        class HtmlFormatter < BaseTextFormatter
+          include ERB::Util
+          
+          def run_started(count)
+            @output.puts <<-EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <title>Stories</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Expires" content="-1" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <script src="javascripts/prototype.js" type="text/javascript"></script>
+    <script src="javascripts/scriptaculous.js" type="text/javascript"></script>
+    <script src="javascripts/rspec.js" type="text/javascript"></script>
+    <link href="stylesheets/rspec.css" rel="stylesheet" type="text/css" />
+  </head>
+  <body>
+    <div id="container">
+EOF
+          end
+
+          def collected_steps(steps)
+            unless steps.empty?
+              @output.puts "      <ul id=\"stock_steps\" style=\"display: none;\">"
+              steps.each do |step|
+                @output.puts "        <li>#{step}</li>"
+              end
+              @output.puts "      </ul>"
+            end
+          end
+
+          def run_ended
+            @output.puts <<-EOF
+    </div>
+  </body>
+</head>
+EOF
+          end
+          
+          def story_started(title, narrative)
+            @output.puts <<-EOF
+      <dl class="story passed">
+        <dt>Story: #{h title}</dt>
+        <dd>
+          <p>
+            #{h(narrative).split("\n").join("<br />")}
+          </p>
+EOF
+          end
+
+          def story_ended(title, narrative)
+            @output.puts <<-EOF
+        </dd>
+      </dl>
+EOF
+          end
+
+          def scenario_started(story_title, scenario_name)
+            @output.puts <<-EOF
+          <dl class="passed">
+            <dt>Scenario: #{h scenario_name}</dt>
+            <dd>
+              <ul class="steps">
+EOF
+          end
+
+          def scenario_ended
+            @output.puts <<-EOF
+              </ul>
+            </dd>
+          </dl>
+EOF
+          end
+          
+          def found_scenario(type, description)
+          end
+
+          def scenario_succeeded(story_title, scenario_name)
+            scenario_ended
+          end
+
+          def scenario_pending(story_title, scenario_name, reason)
+            scenario_ended
+          end
+
+          def scenario_failed(story_title, scenario_name, err)
+            scenario_ended
+          end
+
+          def step_upcoming(type, description, *args)
+          end
+
+          def step_succeeded(type, description, *args)
+            print_step('passed', type, description, *args) # TODO: uses succeeded CSS class
+          end
+
+          def step_pending(type, description, *args)
+            print_step('pending', type, description, *args)
+          end
+
+          def step_failed(type, description, *args)
+            print_step('failed', type, description, *args)
+          end
+          
+          def print_step(klass, type, description, *args)
+            spans = args.map { |arg| "<span class=\"param\">#{arg}</span>" }
+            desc_string = description.step_name
+            arg_regexp = description.arg_regexp           
+            i = -1
+            inner = type.to_s.capitalize + ' ' + desc_string.gsub(arg_regexp) { |param| spans[i+=1] }
+            @output.puts "                <li class=\"#{klass}\">#{inner}</li>"
+          end
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb
new file mode 100644
index 0000000..ad7a2fa
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb
@@ -0,0 +1,131 @@
+require 'spec/runner/formatter/base_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      module Story
+        class PlainTextFormatter < BaseTextFormatter
+          def initialize(options, where)
+            super
+            @successful_scenario_count = 0
+            @pending_scenario_count = 0
+            @failed_scenarios = []
+            @pending_steps = []
+            @previous_type = nil
+          end
+        
+          def run_started(count)
+            @count = count
+            @output.puts "Running #@count scenarios\n\n"
+          end
+
+          def story_started(title, narrative)
+            @current_story_title = title
+            @output.puts "Story: #{title}\n\n"
+            narrative.each_line do |line|
+              @output.print "  "
+              @output.print line
+            end
+          end
+        
+          def story_ended(title, narrative)
+            @output.puts
+            @output.puts
+          end
+
+          def scenario_started(story_title, scenario_name)
+            @current_scenario_name = scenario_name
+            @scenario_already_failed = false
+            @output.print "\n\n  Scenario: #{scenario_name}"
+            @scenario_ok = true
+          end
+        
+          def scenario_succeeded(story_title, scenario_name)
+            @successful_scenario_count += 1
+          end
+        
+          def scenario_failed(story_title, scenario_name, err)
+            @options.backtrace_tweaker.tweak_backtrace(err)
+            @failed_scenarios << [story_title, scenario_name, err] unless @scenario_already_failed
+            @scenario_already_failed = true
+          end
+        
+          def scenario_pending(story_title, scenario_name, msg)
+            @pending_scenario_count += 1 unless @scenario_already_failed
+            @scenario_already_failed = true
+          end
+        
+          def run_ended
+            @output.puts "#@count scenarios: #@successful_scenario_count succeeded, #{@failed_scenarios.size} failed, #@pending_scenario_count pending"
+            unless @pending_steps.empty?
+              @output.puts "\nPending Steps:"
+              @pending_steps.each_with_index do |pending, i|
+                story_name, scenario_name, msg = pending
+                @output.puts "#{i+1}) #{story_name} (#{scenario_name}): #{msg}"
+              end
+            end
+            unless @failed_scenarios.empty?
+              @output.print "\nFAILURES:"
+              @failed_scenarios.each_with_index do |failure, i|
+                title, scenario_name, err = failure
+                @output.print %[
+    #{i+1}) #{title} (#{scenario_name}) FAILED
+    #{err.class}: #{err.message}
+    #{err.backtrace.join("\n")}
+]
+              end
+            end            
+          end
+
+          def step_upcoming(type, description, *args)
+          end
+                  
+          def step_succeeded(type, description, *args)
+            found_step(type, description, false, *args)
+          end
+        
+          def step_pending(type, description, *args)
+            found_step(type, description, false, *args)
+            @pending_steps << [@current_story_title, @current_scenario_name, description]
+            @output.print " (PENDING)"
+            @scenario_ok = false
+          end
+        
+          def step_failed(type, description, *args)
+            found_step(type, description, true, *args)
+            @output.print red(@scenario_ok ? " (FAILED)" : " (SKIPPED)")
+            @scenario_ok = false
+          end
+          
+          def collected_steps(steps)
+          end
+          
+          def method_missing(sym, *args, &block) #:nodoc:
+            # noop - ignore unknown messages
+          end
+
+        private
+
+          def found_step(type, description, failed, *args)
+            desc_string = description.step_name
+            arg_regexp = description.arg_regexp
+            text = if(type == @previous_type)
+              "\n    And "
+            else
+              "\n\n    #{type.to_s.capitalize} "
+            end
+            i = -1
+            text << desc_string.gsub(arg_regexp) { |param| args[i+=1] }
+            @output.print(failed ? red(text) : green(text))
+
+            if type == :'given scenario'
+              @previous_type = :given
+            else
+              @previous_type = type
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/formatter/text_mate_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/text_mate_formatter.rb
new file mode 100644
index 0000000..4c0a9c7
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/formatter/text_mate_formatter.rb
@@ -0,0 +1,16 @@
+require 'spec/runner/formatter/html_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      # Formats backtraces so they're clickable by TextMate
+      class TextMateFormatter < HtmlFormatter
+        def backtrace_line(line)
+          line.gsub(/([^:]*\.rb):(\d*)/) do
+            "<a href=\"txmt://open?url=file://#{File.expand_path($1)}&line=#{$2}\">#{$1}:#{$2}</a> "
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/heckle_runner.rb b/vendor/gems/rspec/lib/spec/runner/heckle_runner.rb
new file mode 100644
index 0000000..7695fe7
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/heckle_runner.rb
@@ -0,0 +1,72 @@
+begin
+  require 'rubygems'
+  require 'heckle'
+rescue LoadError ; raise "You must gem install heckle to use --heckle" ; end
+
+module Spec
+  module Runner
+    # Creates a new Heckler configured to heckle all methods in the classes
+    # whose name matches +filter+
+    class HeckleRunner
+      def initialize(filter, heckle_class=Heckler)
+        @filter = filter
+        @heckle_class = heckle_class
+      end
+      
+      # Runs all the example groups held by +rspec_options+ once for each of the
+      # methods in the matched classes.
+      def heckle_with
+        if @filter =~ /(.*)[#\.](.*)/
+          heckle_method($1, $2)
+        else
+          heckle_class_or_module(@filter)
+        end
+      end
+      
+      def heckle_method(class_name, method_name)
+        verify_constant(class_name)
+        heckle = @heckle_class.new(class_name, method_name, rspec_options)
+        heckle.validate
+      end
+      
+      def heckle_class_or_module(class_or_module_name)
+        verify_constant(class_or_module_name)
+        pattern = /^#{class_or_module_name}/
+        classes = []
+        ObjectSpace.each_object(Class) do |klass|
+          classes << klass if klass.name =~ pattern
+        end
+        
+        classes.each do |klass|
+          klass.instance_methods(false).each do |method_name|
+            heckle = @heckle_class.new(klass.name, method_name, rspec_options)
+            heckle.validate
+          end
+        end
+      end
+      
+      def verify_constant(name)
+        begin
+          # This is defined in Heckle
+          name.to_class
+        rescue
+          raise "Heckling failed - \"#{name}\" is not a known class or module"
+        end
+      end
+    end
+    
+    #Supports Heckle 1.2 and prior (earlier versions used Heckle::Base)
+    class Heckler < (Heckle.const_defined?(:Base) ? Heckle::Base : Heckle)
+      def initialize(klass_name, method_name, rspec_options)
+        super(klass_name, method_name)
+        @rspec_options = rspec_options
+      end
+
+      def tests_pass?
+        success = @rspec_options.run_examples
+        success
+      end
+
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/heckle_runner_unsupported.rb b/vendor/gems/rspec/lib/spec/runner/heckle_runner_unsupported.rb
new file mode 100644
index 0000000..02aa379
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/heckle_runner_unsupported.rb
@@ -0,0 +1,10 @@
+module Spec
+  module Runner
+    # Dummy implementation for Windows that just fails (Heckle is not supported on Windows)
+    class HeckleRunner
+      def initialize(filter)
+        raise "Heckle not supported on Windows"
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/option_parser.rb b/vendor/gems/rspec/lib/spec/runner/option_parser.rb
new file mode 100644
index 0000000..4bc84c8
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/option_parser.rb
@@ -0,0 +1,201 @@
+require 'optparse'
+require 'stringio'
+
+module Spec
+  module Runner
+    class OptionParser < ::OptionParser
+      class << self
+        def parse(args, err, out)
+          parser = new(err, out)
+          parser.parse(args)
+          parser.options
+        end
+      end
+
+      attr_reader :options
+
+      OPTIONS = {
+        :pattern => ["-p", "--pattern [PATTERN]","Limit files loaded to those matching this pattern. Defaults to '**/*_spec.rb'",
+                                                 "Separate multiple patterns with commas.",
+                                                 "Applies only to directories named on the command line (files",
+                                                 "named explicitly on the command line will be loaded regardless)."],
+        :diff =>    ["-D", "--diff [FORMAT]", "Show diff of objects that are expected to be equal when they are not",
+                                             "Builtin formats: unified|u|context|c",
+                                             "You can also specify a custom differ class",
+                                             "(in which case you should also specify --require)"],
+        :colour =>  ["-c", "--colour", "--color", "Show coloured (red/green) output"],
+        :example => ["-e", "--example [NAME|FILE_NAME]",  "Execute example(s) with matching name(s). If the argument is",
+                                                          "the path to an existing file (typically generated by a previous",
+                                                          "run using --format failing_examples:file.txt), then the examples",
+                                                          "on each line of thatfile will be executed. If the file is empty,",
+                                                          "all examples will be run (as if --example was not specified).",
+                                                          " ",
+                                                          "If the argument is not an existing file, then it is treated as",
+                                                          "an example name directly, causing RSpec to run just the example",
+                                                          "matching that name"],
+        :specification => ["-s", "--specification [NAME]", "DEPRECATED - use -e instead", "(This will be removed when autotest works with -e)"],
+        :line => ["-l", "--line LINE_NUMBER", Integer, "Execute behaviout or specification at given line.",
+                                                       "(does not work for dynamically generated specs)"],
+        :format => ["-f", "--format FORMAT[:WHERE]",  "Specifies what format to use for output. Specify WHERE to tell",
+                                                    "the formatter where to write the output. All built-in formats",
+                                                    "expect WHERE to be a file name, and will write to STDOUT if it's",
+                                                    "not specified. The --format option may be specified several times",
+                                                    "if you want several outputs",
+                                                    " ",
+                                                    "Builtin formats for examples: ",
+                                                    "progress|p               : Text progress",
+                                                    "profile|o                : Text progress with profiling of 10 slowest examples",
+                                                    "specdoc|s                : Example doc as text",
+                                                    "html|h                   : A nice HTML report",
+                                                    "failing_examples|e       : Write all failing examples - input for --example",
+                                                    "failing_example_groups|g : Write all failing example groups - input for --example",
+                                                    " ",
+                                                    "Builtin formats for stories: ",
+                                                    "plain|p              : Plain Text",
+                                                    "html|h               : A nice HTML report",
+                                                    " ",
+                                                    "FORMAT can also be the name of a custom formatter class",
+                                                    "(in which case you should also specify --require to load it)"],
+        :require => ["-r", "--require FILE", "Require FILE before running specs",
+                                          "Useful for loading custom formatters or other extensions.",
+                                          "If this option is used it must come before the others"],
+        :backtrace => ["-b", "--backtrace", "Output full backtrace"],
+        :loadby => ["-L", "--loadby STRATEGY", "Specify the strategy by which spec files should be loaded.",
+                                              "STRATEGY can currently only be 'mtime' (File modification time)",
+                                              "By default, spec files are loaded in alphabetical order if --loadby",
+                                              "is not specified."],
+        :reverse => ["-R", "--reverse", "Run examples in reverse order"],
+        :timeout => ["-t", "--timeout FLOAT", "Interrupt and fail each example that doesn't complete in the",
+                                              "specified time"],
+        :heckle => ["-H", "--heckle CODE", "If all examples pass, this will mutate the classes and methods",
+                                           "identified by CODE little by little and run all the examples again",
+                                           "for each mutation. The intent is that for each mutation, at least",
+                                           "one example *should* fail, and RSpec will tell you if this is not the",
+                                           "case. CODE should be either Some::Module, Some::Class or",
+                                           "Some::Fabulous#method}"],
+        :dry_run => ["-d", "--dry-run", "Invokes formatters without executing the examples."],
+        :options_file => ["-O", "--options PATH", "Read options from a file"],
+        :generate_options => ["-G", "--generate-options PATH", "Generate an options file for --options"],
+        :runner => ["-U", "--runner RUNNER", "Use a custom Runner."],
+        :drb => ["-X", "--drb", "Run examples via DRb. (For example against script/spec_server)"],
+        :version => ["-v", "--version", "Show version"],
+        :help => ["-h", "--help", "You're looking at it"]
+      }
+
+      def initialize(err, out)
+        super()
+        @error_stream = err
+        @out_stream = out
+        @options = Options.new(@error_stream, @out_stream)
+
+        @file_factory = File
+
+        self.banner = "Usage: spec (FILE|DIRECTORY|GLOB)+ [options]"
+        self.separator ""
+        on(*OPTIONS[:pattern]) {|pattern| @options.filename_pattern = pattern}
+        on(*OPTIONS[:diff]) {|diff| @options.parse_diff(diff)}
+        on(*OPTIONS[:colour]) {@options.colour = true}
+        on(*OPTIONS[:example]) {|example| @options.parse_example(example)}
+        on(*OPTIONS[:specification]) {|example| @options.parse_example(example)}
+        on(*OPTIONS[:line]) {|line_number| @options.line_number = line_number.to_i}
+        on(*OPTIONS[:format]) {|format| @options.parse_format(format)}
+        on(*OPTIONS[:require]) {|requires| invoke_requires(requires)}
+        on(*OPTIONS[:backtrace]) {@options.backtrace_tweaker = NoisyBacktraceTweaker.new}
+        on(*OPTIONS[:loadby]) {|loadby| @options.loadby = loadby}
+        on(*OPTIONS[:reverse]) {@options.reverse = true}
+        on(*OPTIONS[:timeout]) {|timeout| @options.timeout = timeout.to_f}
+        on(*OPTIONS[:heckle]) {|heckle| @options.load_heckle_runner(heckle)}
+        on(*OPTIONS[:dry_run]) {@options.dry_run = true}
+        on(*OPTIONS[:options_file]) {|options_file| parse_options_file(options_file)}
+        on(*OPTIONS[:generate_options]) do |options_file|
+        end
+        on(*OPTIONS[:runner]) do |runner|
+          @options.user_input_for_runner = runner
+        end
+        on(*OPTIONS[:drb]) {}
+        on(*OPTIONS[:version]) {parse_version}
+        on_tail(*OPTIONS[:help]) {parse_help}
+      end
+
+      def order!(argv, &blk)
+        @argv = argv
+        @options.argv = @argv.dup
+        return if parse_generate_options
+        return if parse_drb
+        
+        super(@argv) do |file|
+          @options.files << file
+          blk.call(file) if blk
+        end
+
+        @options
+      end
+
+      protected
+      def invoke_requires(requires)
+        requires.split(",").each do |file|
+          require file
+        end
+      end
+      
+      def parse_options_file(options_file)
+        option_file_args = IO.readlines(options_file).map {|l| l.chomp.split " "}.flatten
+        @argv.push(*option_file_args)
+      end
+
+      def parse_generate_options
+        # Remove the --generate-options option and the argument before writing to file
+        options_file = nil
+        ['-G', '--generate-options'].each do |option|
+          if index = @argv.index(option)
+            @argv.delete_at(index)
+            options_file = @argv.delete_at(index)
+          end
+        end
+        
+        if options_file
+          write_generated_options(options_file)
+          return true
+        else
+          return false
+        end
+      end
+      
+      def write_generated_options(options_file)
+        File.open(options_file, 'w') do |io|
+          io.puts @argv.join("\n")
+        end
+        @out_stream.puts "\nOptions written to #{options_file}. You can now use these options with:"
+        @out_stream.puts "spec --options #{options_file}"
+        @options.examples_should_not_be_run
+      end
+
+      def parse_drb
+        is_drb = false
+        argv = @options.argv
+        is_drb ||= argv.delete(OPTIONS[:drb][0])
+        is_drb ||= argv.delete(OPTIONS[:drb][1])
+        return nil unless is_drb
+        @options.examples_should_not_be_run
+        DrbCommandLine.run(
+          self.class.parse(argv, @error_stream, @out_stream)
+        )
+        true
+      end
+
+      def parse_version
+        @out_stream.puts ::Spec::VERSION::DESCRIPTION
+        exit if stdout?
+      end
+
+      def parse_help
+        @out_stream.puts self
+        exit if stdout?
+      end      
+
+      def stdout?
+        @out_stream == $stdout
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/options.rb b/vendor/gems/rspec/lib/spec/runner/options.rb
new file mode 100644
index 0000000..108749c
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/options.rb
@@ -0,0 +1,286 @@
+module Spec
+  module Runner
+    class Options
+      FILE_SORTERS = {
+        'mtime' => lambda {|file_a, file_b| File.mtime(file_b) <=> File.mtime(file_a)}
+      }
+
+      EXAMPLE_FORMATTERS = { # Load these lazily for better speed
+               'specdoc' => ['spec/runner/formatter/specdoc_formatter',                'Formatter::SpecdocFormatter'],
+                     's' => ['spec/runner/formatter/specdoc_formatter',                'Formatter::SpecdocFormatter'],
+                  'html' => ['spec/runner/formatter/html_formatter',                   'Formatter::HtmlFormatter'],
+                     'h' => ['spec/runner/formatter/html_formatter',                   'Formatter::HtmlFormatter'],
+              'progress' => ['spec/runner/formatter/progress_bar_formatter',           'Formatter::ProgressBarFormatter'],
+                     'p' => ['spec/runner/formatter/progress_bar_formatter',           'Formatter::ProgressBarFormatter'],
+      'failing_examples' => ['spec/runner/formatter/failing_examples_formatter',       'Formatter::FailingExamplesFormatter'],
+                     'e' => ['spec/runner/formatter/failing_examples_formatter',       'Formatter::FailingExamplesFormatter'],
+'failing_example_groups' => ['spec/runner/formatter/failing_example_groups_formatter', 'Formatter::FailingExampleGroupsFormatter'],
+                     'g' => ['spec/runner/formatter/failing_example_groups_formatter', 'Formatter::FailingExampleGroupsFormatter'],
+               'profile' => ['spec/runner/formatter/profile_formatter',                'Formatter::ProfileFormatter'],
+                     'o' => ['spec/runner/formatter/profile_formatter',                'Formatter::ProfileFormatter'],
+              'textmate' => ['spec/runner/formatter/text_mate_formatter',              'Formatter::TextMateFormatter']
+      }
+
+      STORY_FORMATTERS = {
+        'plain' => ['spec/runner/formatter/story/plain_text_formatter', 'Formatter::Story::PlainTextFormatter'],
+            'p' => ['spec/runner/formatter/story/plain_text_formatter', 'Formatter::Story::PlainTextFormatter'],
+         'html' => ['spec/runner/formatter/story/html_formatter',       'Formatter::Story::HtmlFormatter'],
+            'h' => ['spec/runner/formatter/story/html_formatter',       'Formatter::Story::HtmlFormatter']
+      }
+
+      attr_accessor(
+        :filename_pattern,
+        :backtrace_tweaker,
+        :context_lines,
+        :diff_format,
+        :dry_run,
+        :profile,
+        :examples,
+        :heckle_runner,
+        :line_number,
+        :loadby,
+        :reporter,
+        :reverse,
+        :timeout,
+        :verbose,
+        :user_input_for_runner,
+        :error_stream,
+        :output_stream,
+        # TODO: BT - Figure out a better name
+        :argv
+      )
+      attr_reader :colour, :differ_class, :files, :example_groups
+
+      def initialize(error_stream, output_stream)
+        @error_stream = error_stream
+        @output_stream = output_stream
+        @filename_pattern = "**/*_spec.rb"
+        @backtrace_tweaker = QuietBacktraceTweaker.new
+        @examples = []
+        @colour = false
+        @profile = false
+        @dry_run = false
+        @reporter = Reporter.new(self)
+        @context_lines = 3
+        @diff_format  = :unified
+        @files = []
+        @example_groups = []
+        @examples_run = false
+        @examples_should_be_run = nil
+        @user_input_for_runner = nil
+      end
+
+      def add_example_group(example_group)
+        @example_groups << example_group
+      end
+
+      def remove_example_group(example_group)
+        @example_groups.delete(example_group)
+      end
+
+      def run_examples
+        return true unless examples_should_be_run?
+        runner = custom_runner || ExampleGroupRunner.new(self)
+
+        runner.load_files(files_to_load)
+        if example_groups.empty?
+          true
+        else
+          set_spec_from_line_number if line_number
+          success = runner.run
+          @examples_run = true
+          heckle if heckle_runner
+          success
+        end
+      end
+
+      def examples_run?
+        @examples_run
+      end
+
+      def examples_should_not_be_run
+        @examples_should_be_run = false
+      end      
+
+      def colour=(colour)
+        @colour = colour
+        if @colour && RUBY_PLATFORM =~ /win32/ ;\
+          begin ;\
+            require 'rubygems' ;\
+            require 'Win32/Console/ANSI' ;\
+          rescue LoadError ;\
+            warn "You must 'gem install win32console' to use colour on Windows" ;\
+            @colour = false ;\
+          end
+        end
+      end
+
+      def parse_diff(format)
+        case format
+        when :context, 'context', 'c'
+          @diff_format  = :context
+          default_differ
+        when :unified, 'unified', 'u', '', nil
+          @diff_format  = :unified
+          default_differ
+        else
+          @diff_format  = :custom
+          self.differ_class = load_class(format, 'differ', '--diff')
+        end
+      end
+
+      def parse_example(example)
+        if(File.file?(example))
+          @examples = File.open(example).read.split("\n")
+        else
+          @examples = [example]
+        end
+      end
+
+      def parse_format(format_arg)
+        format, where = ClassAndArgumentsParser.parse(format_arg)
+        unless where
+          raise "When using several --format options only one of them can be without a file" if @out_used
+          where = @output_stream
+          @out_used = true
+        end
+        @format_options ||= []
+        @format_options << [format, where]
+      end
+      
+      def formatters
+        @format_options ||= [['progress', @output_stream]]
+        @formatters ||= load_formatters(@format_options, EXAMPLE_FORMATTERS)
+      end
+
+      def story_formatters
+        @format_options ||= [['plain', @output_stream]]
+        @formatters ||= load_formatters(@format_options, STORY_FORMATTERS)
+      end
+      
+      def load_formatters(format_options, formatters)
+        format_options.map do |format, where|
+          formatter_type = if formatters[format]
+            require formatters[format][0]
+            eval(formatters[format][1], binding, __FILE__, __LINE__)
+          else
+            load_class(format, 'formatter', '--format')
+          end
+          formatter_type.new(self, where)
+        end
+      end
+
+      def load_heckle_runner(heckle)
+        suffix = [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} ? '_unsupported' : ''
+        require "spec/runner/heckle_runner#{suffix}"
+        @heckle_runner = HeckleRunner.new(heckle)
+      end
+
+      def number_of_examples
+        @example_groups.inject(0) do |sum, example_group|
+          sum + example_group.number_of_examples
+        end
+      end
+
+      def files_to_load
+        result = []
+        sorted_files.each do |file|
+          if File.directory?(file)
+            filename_pattern.split(",").each do |pattern|
+              result += Dir[File.expand_path("#{file}/#{pattern.strip}")]
+            end
+          elsif File.file?(file)
+            result << file
+          else
+            raise "File or directory not found: #{file}"
+          end
+        end
+        result
+      end
+      
+      protected
+      def examples_should_be_run?
+        return @examples_should_be_run unless @examples_should_be_run.nil?
+        @examples_should_be_run = true
+      end
+      
+      def differ_class=(klass)
+        return unless klass
+        @differ_class = klass
+        Spec::Expectations.differ = self.differ_class.new(self)
+      end
+
+      def load_class(name, kind, option)
+        if name =~ /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/
+          arg = $2 == "" ? nil : $2
+          [$1, arg]
+        else
+          m = "#{name.inspect} is not a valid class name"
+          @error_stream.puts m
+          raise m
+        end
+        begin
+          eval(name, binding, __FILE__, __LINE__)
+        rescue NameError => e
+          @error_stream.puts "Couldn't find #{kind} class #{name}"
+          @error_stream.puts "Make sure the --require option is specified *before* #{option}"
+          if $_spec_spec ; raise e ; else exit(1) ; end
+        end
+      end
+      
+      def custom_runner
+        return nil unless custom_runner?
+        klass_name, arg = ClassAndArgumentsParser.parse(user_input_for_runner)
+        runner_type = load_class(klass_name, 'behaviour runner', '--runner')
+        return runner_type.new(self, arg)
+      end
+
+      def custom_runner?
+        return user_input_for_runner ? true : false
+      end
+      
+      def heckle
+        returns = self.heckle_runner.heckle_with
+        self.heckle_runner = nil
+        returns
+      end
+      
+      def sorted_files
+        return sorter ? files.sort(&sorter) : files
+      end
+
+      def sorter
+        FILE_SORTERS[loadby]
+      end
+
+      def default_differ
+        require 'spec/expectations/differs/default'
+        self.differ_class = Spec::Expectations::Differs::Default
+      end
+
+      def set_spec_from_line_number
+        if examples.empty?
+          if files.length == 1
+            if File.directory?(files[0])
+              error_stream.puts "You must specify one file, not a directory when using the --line option"
+              exit(1) if stderr?
+            else
+              example = SpecParser.new.spec_name_for(files[0], line_number)
+              @examples = [example]
+            end
+          else
+            error_stream.puts "Only one file can be specified when using the --line option: #{files.inspect}"
+            exit(3) if stderr?
+          end
+        else
+          error_stream.puts "You cannot use both --line and --example"
+          exit(4) if stderr?
+        end
+      end
+
+      def stderr?
+        @error_stream == $stderr
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/reporter.rb b/vendor/gems/rspec/lib/spec/runner/reporter.rb
new file mode 100644
index 0000000..cfc511b
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/reporter.rb
@@ -0,0 +1,143 @@
+module Spec
+  module Runner
+    class Reporter
+      attr_reader :options, :example_groups
+      
+      def initialize(options)
+        @options = options
+        @options.reporter = self
+        clear
+      end
+      
+      def add_example_group(example_group)
+        formatters.each do |f|
+          f.add_example_group(example_group)
+        end
+        example_groups << example_group
+      end
+      
+      def example_started(example)
+        formatters.each{|f| f.example_started(example)}
+      end
+      
+      def example_finished(example, error=nil)
+        @examples << example
+        
+        if error.nil?
+          example_passed(example)
+        elsif Spec::Example::ExamplePendingError === error
+          example_pending(example_groups.last, example, error.message)
+        else
+          example_failed(example, error)
+        end
+      end
+
+      def failure(example, error)
+        backtrace_tweaker.tweak_backtrace(error)
+        example_name = "#{example_groups.last.description} #{example.description}"
+        failure = Failure.new(example_name, error)
+        @failures << failure
+        formatters.each do |f|
+          f.example_failed(example, @failures.length, failure)
+        end
+      end
+      alias_method :example_failed, :failure
+
+      def start(number_of_examples)
+        clear
+        @start_time = Time.new
+        formatters.each{|f| f.start(number_of_examples)}
+      end
+  
+      def end
+        @end_time = Time.new
+      end
+  
+      # Dumps the summary and returns the total number of failures
+      def dump
+        formatters.each{|f| f.start_dump}
+        dump_pending
+        dump_failures
+        formatters.each do |f|
+          f.dump_summary(duration, @examples.length, @failures.length, @pending_count)
+          f.close
+        end
+        @failures.length
+      end
+
+    private
+
+      def formatters
+        @options.formatters
+      end
+
+      def backtrace_tweaker
+        @options.backtrace_tweaker
+      end
+  
+      def clear
+        @example_groups = []
+        @failures = []
+        @pending_count = 0
+        @examples = []
+        @start_time = nil
+        @end_time = nil
+      end
+  
+      def dump_failures
+        return if @failures.empty?
+        @failures.inject(1) do |index, failure|
+          formatters.each{|f| f.dump_failure(index, failure)}
+          index + 1
+        end
+      end
+      def dump_pending
+        formatters.each{|f| f.dump_pending}
+      end
+
+      def duration
+        return @end_time - @start_time unless (@end_time.nil? or @start_time.nil?)
+        return "0.0"
+      end
+      
+      def example_passed(example)
+        formatters.each{|f| f.example_passed(example)}
+      end
+      
+      def example_pending(example_group, example, message="Not Yet Implemented")
+        @pending_count += 1
+        formatters.each do |f|
+          f.example_pending(example_group.description, example, message)
+        end
+      end
+      
+      class Failure
+        attr_reader :exception
+        
+        def initialize(example_name, exception)
+          @example_name = example_name
+          @exception = exception
+        end
+
+        def header
+          if expectation_not_met?
+            "'#{@example_name}' FAILED"
+          elsif pending_fixed?
+            "'#{@example_name}' FIXED"
+          else
+            "#{@exception.class.name} in '#{@example_name}'"
+          end
+        end
+        
+        def pending_fixed?
+          @exception.is_a?(Spec::Example::PendingExampleFixedError)
+        end
+
+        def expectation_not_met?
+          @exception.is_a?(Spec::Expectations::ExpectationNotMetError)
+        end
+
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/runner/spec_parser.rb b/vendor/gems/rspec/lib/spec/runner/spec_parser.rb
new file mode 100644
index 0000000..8beb384
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/runner/spec_parser.rb
@@ -0,0 +1,71 @@
+module Spec
+  module Runner
+    # Parses a spec file and finds the nearest example for a given line number.
+    class SpecParser
+      attr_reader :best_match
+
+      def initialize
+        @best_match = {}
+      end
+
+      def spec_name_for(file, line_number)
+        best_match.clear
+        file = File.expand_path(file)
+        rspec_options.example_groups.each do |example_group|
+          consider_example_groups_for_best_match example_group, file, line_number
+
+          example_group.examples.each do |example|
+            consider_example_for_best_match example, example_group, file, line_number
+          end
+        end
+        if best_match[:example_group]
+          if best_match[:example]
+            "#{best_match[:example_group].description} #{best_match[:example].description}"
+          else
+            best_match[:example_group].description
+          end
+        else
+          nil
+        end
+      end
+
+    protected
+
+      def consider_example_groups_for_best_match(example_group, file, line_number)
+        parsed_backtrace = parse_backtrace(example_group.registration_backtrace)
+        parsed_backtrace.each do |example_file, example_line|
+          if is_best_match?(file, line_number, example_file, example_line)
+            best_match.clear
+            best_match[:example_group] = example_group
+            best_match[:line] = example_line
+          end
+        end
+      end
+
+      def consider_example_for_best_match(example, example_group, file, line_number)
+        parsed_backtrace = parse_backtrace(example.implementation_backtrace)
+        parsed_backtrace.each do |example_file, example_line|
+          if is_best_match?(file, line_number, example_file, example_line)
+            best_match.clear
+            best_match[:example_group] = example_group
+            best_match[:example] = example
+            best_match[:line] = example_line
+          end
+        end
+      end
+
+      def is_best_match?(file, line_number, example_file, example_line)
+        file == File.expand_path(example_file) &&
+        example_line <= line_number &&
+        example_line > best_match[:line].to_i
+      end
+
+      def parse_backtrace(backtrace)
+        backtrace.collect do |trace_line|
+          split_line = trace_line.split(':')
+          [split_line[0], Integer(split_line[1])]
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story.rb b/vendor/gems/rspec/lib/spec/story.rb
new file mode 100644
index 0000000..bc6960a
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story.rb
@@ -0,0 +1,10 @@
+require 'spec'
+require 'spec/story/extensions'
+require 'spec/story/given_scenario'
+require 'spec/story/runner'
+require 'spec/story/scenario'
+require 'spec/story/step'
+require 'spec/story/step_group'
+require 'spec/story/step_mother'
+require 'spec/story/story'
+require 'spec/story/world'
diff --git a/vendor/gems/rspec/lib/spec/story/extensions.rb b/vendor/gems/rspec/lib/spec/story/extensions.rb
new file mode 100644
index 0000000..dc7dd11
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/extensions.rb
@@ -0,0 +1,3 @@
+require 'spec/story/extensions/main'
+require 'spec/story/extensions/string'
+require 'spec/story/extensions/regexp'
diff --git a/vendor/gems/rspec/lib/spec/story/extensions/main.rb b/vendor/gems/rspec/lib/spec/story/extensions/main.rb
new file mode 100644
index 0000000..6336b63
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/extensions/main.rb
@@ -0,0 +1,86 @@
+module Spec
+  module Story
+    module Extensions
+      module Main
+        def Story(title, narrative, params = {}, &body)
+          ::Spec::Story::Runner.story_runner.Story(title, narrative, params, &body)
+        end
+      
+        # Calling this deprecated is silly, since it hasn't been released yet. But, for
+        # those who are reading this - this will be deleted before the 1.1 release.
+        def run_story(*args, &block)
+          runner = Spec::Story::Runner::PlainTextStoryRunner.new(*args)
+          runner.instance_eval(&block) if block
+          runner.run
+        end
+      
+        # Creates (or appends to an existing) a namespaced group of steps for use in Stories
+        #
+        # == Examples
+        #
+        #   # Creating a new group
+        #   steps_for :forms do
+        #     When("user enters $value in the $field field") do ... end
+        #     When("user submits the $form form") do ... end
+        #   end
+        def steps_for(tag, &block)
+          steps = rspec_story_steps[tag]
+          steps.instance_eval(&block) if block
+          steps
+        end
+      
+        # Creates a context for running a Plain Text Story with specific groups of Steps. 
+        # Also supports adding arbitrary steps that will only be accessible to
+        # the Story being run.
+        #
+        # == Examples
+        #
+        #   # Run a Story with one group of steps
+        #   with_steps_for :checking_accounts do
+        #     run File.dirname(__FILE__) + "/withdraw_cash"
+        #   end
+        #
+        #   # Run a Story, adding steps that are only available for this Story
+        #   with_steps_for :accounts do
+        #     Given "user is logged in as account administrator"
+        #     run File.dirname(__FILE__) + "/reconcile_accounts"
+        #   end
+        #
+        #   # Run a Story with steps from two groups
+        #   with_steps_for :checking_accounts, :savings_accounts do
+        #     run File.dirname(__FILE__) + "/transfer_money"
+        #   end
+        #
+        #   # Run a Story with a specific Story extension
+        #   with_steps_for :login, :navigation do
+        #     run File.dirname(__FILE__) + "/user_changes_password", :type => RailsStory
+        #   end
+        def with_steps_for(*tags, &block)
+          steps = Spec::Story::StepGroup.new do
+            extend StoryRunnerStepGroupAdapter
+          end
+          tags.each {|tag| steps << rspec_story_steps[tag]}
+          steps.instance_eval(&block) if block
+          steps
+        end
+
+      private
+
+        module StoryRunnerStepGroupAdapter
+          def run(path, options={})
+            runner = Spec::Story::Runner::PlainTextStoryRunner.new(path, options)
+            runner.steps << self
+            runner.run
+          end
+        end
+        
+        def rspec_story_steps  # :nodoc:
+          $rspec_story_steps ||= Spec::Story::StepGroupHash.new
+        end
+                
+      end
+    end
+  end
+end
+
+include Spec::Story::Extensions::Main
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/story/extensions/regexp.rb b/vendor/gems/rspec/lib/spec/story/extensions/regexp.rb
new file mode 100644
index 0000000..7955b4c
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/extensions/regexp.rb
@@ -0,0 +1,9 @@
+class Regexp
+  def step_name
+    self.source
+  end
+  
+  def arg_regexp
+    ::Spec::Story::Step::PARAM_OR_GROUP_PATTERN
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/story/extensions/string.rb b/vendor/gems/rspec/lib/spec/story/extensions/string.rb
new file mode 100644
index 0000000..896578d
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/extensions/string.rb
@@ -0,0 +1,9 @@
+class String
+  def step_name
+    self
+  end
+  
+  def arg_regexp
+    ::Spec::Story::Step::PARAM_PATTERN
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/story/given_scenario.rb b/vendor/gems/rspec/lib/spec/story/given_scenario.rb
new file mode 100644
index 0000000..88c51f9
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/given_scenario.rb
@@ -0,0 +1,14 @@
+module Spec
+  module Story
+    class GivenScenario
+      def initialize(name)
+        @name = name
+      end
+      
+      def perform(instance, ignore_name)
+        scenario = Runner::StoryRunner.scenario_from_current_story(@name)
+        Runner::ScenarioRunner.new.run(scenario, instance)
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/runner.rb b/vendor/gems/rspec/lib/spec/story/runner.rb
new file mode 100644
index 0000000..1f6dd9e
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/runner.rb
@@ -0,0 +1,56 @@
+require 'spec/story/runner/scenario_collector.rb'
+require 'spec/story/runner/scenario_runner.rb'
+require 'spec/story/runner/story_runner.rb'
+require 'spec/story/runner/story_parser.rb'
+require 'spec/story/runner/story_mediator.rb'
+require 'spec/story/runner/plain_text_story_runner.rb'
+
+module Spec
+  module Story
+    module Runner
+      class << self
+        def run_options # :nodoc:
+          @run_options ||= ::Spec::Runner::OptionParser.parse(ARGV, $stderr, $stdout)
+        end
+        
+        def story_runner # :nodoc:
+          unless @story_runner
+            @story_runner = StoryRunner.new(scenario_runner, world_creator)
+            run_options.story_formatters.each do |formatter|
+              register_listener(formatter)
+            end
+            Runner.register_exit_hook
+          end
+          @story_runner
+        end
+        
+        def scenario_runner # :nodoc:
+          @scenario_runner ||= ScenarioRunner.new
+        end
+        
+        def world_creator # :nodoc:
+          @world_creator ||= World
+        end
+        
+        # Use this to register a customer output formatter.
+        def register_listener(listener)
+          story_runner.add_listener(listener) # run_started, story_started, story_ended, #run_ended
+          world_creator.add_listener(listener) # found_scenario, step_succeeded, step_failed, step_failed
+          scenario_runner.add_listener(listener) # scenario_started, scenario_succeeded, scenario_pending, scenario_failed
+        end
+        
+        def register_exit_hook # :nodoc:
+          at_exit do
+            Runner.story_runner.run_stories unless $!
+          end
+          # TODO exit with non-zero status if run fails
+        end
+        
+        def dry_run
+          run_options.dry_run
+        end
+        
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/runner/plain_text_story_runner.rb b/vendor/gems/rspec/lib/spec/story/runner/plain_text_story_runner.rb
new file mode 100644
index 0000000..8d34ea2
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/runner/plain_text_story_runner.rb
@@ -0,0 +1,48 @@
+module Spec
+  module Story
+    module Runner
+      class PlainTextStoryRunner
+        # You can initialize a PlainTextStoryRunner with the path to the
+        # story file or a block, in which you can define the path using load.
+        #
+        # == Examples
+        #   
+        #   PlainTextStoryRunner.new('path/to/file')
+        #
+        #   PlainTextStoryRunner.new do |runner|
+        #     runner.load 'path/to/file'
+        #   end
+        def initialize(*args)
+          @options = Hash === args.last ? args.pop : {}
+          @story_file = args.empty? ? nil : args.shift
+          yield self if block_given?
+        end
+        
+        def []=(key, value)
+          @options[key] = value
+        end
+        
+        def load(path)
+          @story_file = path
+        end
+        
+        def run
+          raise "You must set a path to the file with the story. See the RDoc." if @story_file.nil?
+          mediator = Spec::Story::Runner::StoryMediator.new(steps, Spec::Story::Runner.story_runner, @options)
+          parser = Spec::Story::Runner::StoryParser.new(mediator)
+
+          story_text = File.read(@story_file)          
+          parser.parse(story_text.split("\n"))
+
+          mediator.run_stories
+        end
+        
+        def steps
+          @step_group ||= Spec::Story::StepGroup.new
+          yield @step_group if block_given?
+          @step_group
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/runner/scenario_collector.rb b/vendor/gems/rspec/lib/spec/story/runner/scenario_collector.rb
new file mode 100644
index 0000000..78339fd
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/runner/scenario_collector.rb
@@ -0,0 +1,18 @@
+module Spec
+  module Story
+    module Runner
+      class ScenarioCollector
+        attr_accessor :scenarios
+        
+        def initialize(story)
+          @story = story
+          @scenarios = []
+        end
+        
+        def Scenario(name, &body)
+          @scenarios << Scenario.new(@story, name, &body)
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/runner/scenario_runner.rb b/vendor/gems/rspec/lib/spec/story/runner/scenario_runner.rb
new file mode 100644
index 0000000..aee52e4
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/runner/scenario_runner.rb
@@ -0,0 +1,46 @@
+module Spec
+  module Story
+    module Runner
+      class ScenarioRunner
+        def initialize
+          @listeners = []
+        end
+        
+        def run(scenario, world)
+          @listeners.each { |l| l.scenario_started(scenario.story.title, scenario.name) }
+          run_story_ignoring_scenarios(scenario.story, world)
+          
+          world.start_collecting_errors
+          world.instance_eval(&scenario.body)
+          if world.errors.empty?
+            @listeners.each { |l| l.scenario_succeeded(scenario.story.title, scenario.name) }
+          else
+            if Spec::Example::ExamplePendingError === (e = world.errors.first)
+              @listeners.each { |l| l.scenario_pending(scenario.story.title, scenario.name, e.message) }
+            else
+              @listeners.each { |l| l.scenario_failed(scenario.story.title, scenario.name, e) }
+            end
+          end
+        end
+        
+        def add_listener(listener)
+          @listeners << listener
+        end
+        
+        private
+        
+        def run_story_ignoring_scenarios(story, world)
+          class << world
+            def Scenario(name, &block)
+              # do nothing
+            end
+          end
+          story.run_in(world)
+          class << world
+            remove_method(:Scenario)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/runner/story_mediator.rb b/vendor/gems/rspec/lib/spec/story/runner/story_mediator.rb
new file mode 100644
index 0000000..1f4744b
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/runner/story_mediator.rb
@@ -0,0 +1,123 @@
+ module Spec
+  module Story
+    module Runner
+
+      class StoryMediator
+        def initialize(step_group, runner, options={})
+          @step_group = step_group
+          @stories = []
+          @runner = runner
+          @options = options
+        end
+        
+        def stories
+          @stories.collect { |p| p.to_proc }
+        end
+        
+        def create_story(title, narrative)
+          @stories << Story.new(title, narrative, @step_group, @options)
+        end
+        
+        def create_scenario(title)
+          current_story.add_scenario Scenario.new(title)
+        end
+        
+        def create_given(name)
+          current_scenario.add_step Step.new('Given', name)
+        end
+        
+        def create_given_scenario(name)
+          current_scenario.add_step Step.new('GivenScenario', name)
+        end
+        
+        def create_when(name)
+          current_scenario.add_step Step.new('When', name)
+        end
+        
+        def create_then(name)
+          current_scenario.add_step Step.new('Then', name)
+        end
+        
+        def run_stories
+          stories.each { |story| @runner.instance_eval(&story) }
+        end
+        
+        private
+        def current_story
+          @stories.last
+        end
+        
+        def current_scenario
+          current_story.current_scenario
+        end
+        
+        class Story
+          def initialize(title, narrative, step_group, options)
+            @title = title
+            @narrative = narrative
+            @scenarios = []
+            @step_group = step_group
+            @options = options
+          end
+          
+          def to_proc
+            title = @title
+            narrative = @narrative
+            scenarios = @scenarios.collect { |scenario| scenario.to_proc }
+            options = @options.merge(:steps => @step_group)
+            lambda do
+              Story title, narrative, options do
+                scenarios.each { |scenario| instance_eval(&scenario) }
+              end
+            end
+          end
+          
+          def add_scenario(scenario)
+            @scenarios << scenario
+          end
+          
+          def current_scenario
+            @scenarios.last
+          end
+        end
+        
+        class Scenario
+          def initialize(name)
+            @name = name
+            @steps = []
+          end
+          
+          def to_proc
+            name = @name
+            steps = @steps.collect { |step| step.to_proc }
+            lambda do
+              Scenario name do
+                steps.each { |step| instance_eval(&step) }
+              end
+            end
+          end
+          
+          def add_step(step)
+            @steps << step
+          end
+        end
+        
+        class Step
+          def initialize(type, name)
+            @type = type
+            @name = name
+          end
+          
+          def to_proc
+            type = @type
+            name = @name
+            lambda do
+              send(type, name)
+            end
+          end
+        end
+      end
+      
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/runner/story_parser.rb b/vendor/gems/rspec/lib/spec/story/runner/story_parser.rb
new file mode 100644
index 0000000..d454df8
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/runner/story_parser.rb
@@ -0,0 +1,227 @@
+module Spec
+  module Story
+    module Runner
+      
+      class IllegalStepError < StandardError
+        def initialize(state, event)
+          super("Illegal attempt to create a #{event} after a #{state}")
+        end
+      end
+
+      class StoryParser
+        def initialize(story_mediator)
+          @story_mediator = story_mediator
+          @current_story_lines = []
+          transition_to(:starting_state)
+        end
+        
+        def parse(lines)
+          lines.reject! {|line| line == ""}
+          until lines.empty?
+            process_line(lines.shift)
+          end
+          @state.eof
+        end
+        
+        def process_line(line)
+          line.strip!
+          case line
+          when /^Story: /           then @state.story(line)
+          when /^Scenario: /        then @state.scenario(line)
+          when /^Given:? /          then @state.given(line)
+          when /^GivenScenario:? /  then @state.given_scenario(line)
+          when /^When:? /           then @state.event(line)
+          when /^Then:? /           then @state.outcome(line)
+          when /^And:? /            then @state.one_more_of_the_same(line)
+          else                           @state.other(line)
+          end
+        end
+
+        def init_story(title)
+          @current_story_lines.clear
+          add_story_line(title)
+        end
+        
+        def add_story_line(line)
+          @current_story_lines << line
+        end
+        
+        def create_story()
+          unless @current_story_lines.empty?
+            @story_mediator.create_story(@current_story_lines[0].gsub("Story: ",""), @current_story_lines[1..-1].join("\n"))
+            @current_story_lines.clear
+          end
+        end
+        
+        def create_scenario(title)
+          @story_mediator.create_scenario(title.gsub("Scenario: ",""))
+        end
+        
+        def create_given(name)
+          @story_mediator.create_given(name)
+        end
+        
+        def create_given_scenario(name)
+          @story_mediator.create_given_scenario(name)
+        end
+        
+        def create_when(name)
+          @story_mediator.create_when(name)
+        end
+        
+        def create_then(name)
+          @story_mediator.create_then(name)
+        end
+
+        def transition_to(key)
+          @state = states[key]
+        end
+        
+        def states
+          @states ||= {
+            :starting_state => StartingState.new(self),
+            :story_state => StoryState.new(self),
+            :scenario_state => ScenarioState.new(self),
+            :given_state => GivenState.new(self),
+            :when_state => WhenState.new(self),
+            :then_state => ThenState.new(self)
+          }
+        end
+        
+        class State
+          def initialize(parser)
+            @parser = parser
+          end
+          
+          def story(line)
+            @parser.init_story(line)
+            @parser.transition_to(:story_state)
+          end
+
+          def scenario(line)
+            @parser.create_scenario(line)
+            @parser.transition_to(:scenario_state)
+          end
+
+          def given(line)
+            @parser.create_given(remove_tag_from(:given, line))
+            @parser.transition_to(:given_state)
+          end
+          
+          def given_scenario(line)
+            @parser.create_given_scenario(remove_tag_from(:givenscenario, line))
+            @parser.transition_to(:given_state)
+          end
+          
+          def event(line)
+            @parser.create_when(remove_tag_from(:when, line))
+            @parser.transition_to(:when_state)
+          end
+          
+          def outcome(line)
+            @parser.create_then(remove_tag_from(:then, line))
+            @parser.transition_to(:then_state)
+          end
+
+          def remove_tag_from(tag, line)
+            tokens = line.split
+            # validation of tag can go here
+            tokens[0].downcase.match(/#{tag.to_s}:?/) ? 
+                                (tokens[1..-1].join(' ')) : line
+          end
+
+          def eof
+          end
+          
+          def other(line)
+            # no-op - supports header text before the first story in a file
+          end
+        end
+        
+        class StartingState < State
+          def initialize(parser)
+            @parser = parser
+          end
+        end
+        
+        class StoryState < State
+          def one_more_of_the_same(line)
+            other(line)
+          end
+
+          def story(line)
+            @parser.create_story
+            @parser.add_story_line(line)
+          end
+          
+          def scenario(line)
+            @parser.create_story
+            @parser.create_scenario(line)
+            @parser.transition_to(:scenario_state)
+          end
+          
+          def given(line)
+            other(line)
+          end
+          
+          def event(line)
+            other(line)
+          end
+          
+          def outcome(line)
+            other(line)
+          end
+          
+          def other(line)
+            @parser.add_story_line(line)
+          end
+          
+          def eof
+            @parser.create_story
+          end
+        end
+
+        class ScenarioState < State
+          def one_more_of_the_same(line)
+            raise IllegalStepError.new("Scenario", "And")
+          end
+
+          def scenario(line)
+            @parser.create_scenario(line)
+          end
+        end
+        
+        class GivenState < State
+          def one_more_of_the_same(line)
+            @parser.create_given(remove_tag_from(:and, line))
+          end
+          
+          def given(line)
+            @parser.create_given(remove_tag_from(:given, line))
+          end
+        end
+        
+        class WhenState < State
+          def one_more_of_the_same(line)
+            @parser.create_when(remove_tag_from(:and ,line))
+          end
+
+          def event(line)
+            @parser.create_when(remove_tag_from(:when ,line))
+          end
+        end
+
+        class ThenState < State
+          def one_more_of_the_same(line)
+            @parser.create_then(remove_tag_from(:and ,line))
+          end
+
+          def outcome(line)
+            @parser.create_then(remove_tag_from(:then ,line))
+          end
+        end
+
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/runner/story_runner.rb b/vendor/gems/rspec/lib/spec/story/runner/story_runner.rb
new file mode 100644
index 0000000..f9eeb9a
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/runner/story_runner.rb
@@ -0,0 +1,68 @@
+module Spec
+  module Story
+    module Runner
+      class StoryRunner
+        class << self
+          attr_accessor :current_story_runner
+          
+          def scenario_from_current_story(scenario_name)
+            current_story_runner.scenario_from_current_story(scenario_name)
+          end
+        end
+        
+        attr_accessor :stories, :scenarios, :current_story
+        
+        def initialize(scenario_runner, world_creator = World)
+          StoryRunner.current_story_runner = self
+          @scenario_runner = scenario_runner
+          @world_creator = world_creator
+          @stories = []
+          @scenarios_by_story = {}
+          @scenarios = []
+          @listeners = []
+        end
+        
+        def Story(title, narrative, params = {}, &body)
+          story = Story.new(title, narrative, params, &body)
+          @stories << story
+          
+          # collect scenarios
+          collector = ScenarioCollector.new(story)
+          story.run_in(collector)
+          @scenarios += collector.scenarios
+          @scenarios_by_story[story.title] = collector.scenarios
+        end
+        
+        def run_stories
+          return if @stories.empty?
+          @listeners.each { |l| l.run_started(scenarios.size) }
+          @stories.each do |story|
+            story.assign_steps_to(World)
+            @current_story = story
+            @listeners.each { |l| l.story_started(story.title, story.narrative) }
+            scenarios = @scenarios_by_story[story.title]
+            scenarios.each do |scenario|
+              type = story[:type] || Object
+              args = story[:args] || []
+              world = @world_creator.create(type, *args)
+              @scenario_runner.run(scenario, world)
+            end
+            @listeners.each { |l| l.story_ended(story.title, story.narrative) }
+            World.step_mother.clear
+          end
+          unique_steps = (World.step_names.collect {|n| Regexp === n ? n.source : n.to_s}).uniq.sort
+          @listeners.each { |l| l.collected_steps(unique_steps) }
+          @listeners.each { |l| l.run_ended }
+        end
+        
+        def add_listener(listener)
+          @listeners << listener
+        end
+        
+        def scenario_from_current_story(scenario_name)
+          @scenarios_by_story[@current_story.title].find {|s| s.name == scenario_name }
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/scenario.rb b/vendor/gems/rspec/lib/spec/story/scenario.rb
new file mode 100644
index 0000000..d83b3ee
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/scenario.rb
@@ -0,0 +1,14 @@
+
+module Spec
+  module Story
+    class Scenario
+      attr_accessor :name, :body, :story
+      
+      def initialize(story, name, &body)
+        @story = story
+        @name = name
+        @body = body
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/step.rb b/vendor/gems/rspec/lib/spec/story/step.rb
new file mode 100644
index 0000000..ee9ede0
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/step.rb
@@ -0,0 +1,58 @@
+module Spec
+  module Story
+    class Step
+      PARAM_PATTERN = /(\$\w*)/
+      PARAM_OR_GROUP_PATTERN = /(\$\w*)|\(.*?\)/
+      
+      attr_reader :name
+      def initialize(name, &block)
+        @name = name
+        assign_expression(name)
+        init_module(name, &block)
+      end
+
+      def perform(instance, *args)
+        instance.extend(@mod)
+        instance.__send__(sanitize(@name), *args)
+      end
+
+      def init_module(name, &block)
+        sanitized_name = sanitize(name)
+        @mod = Module.new do
+          define_method(sanitized_name, &block)
+        end
+      end
+      
+      def sanitize(a_string_or_regexp)
+        return a_string_or_regexp.source if Regexp == a_string_or_regexp
+        a_string_or_regexp.to_s
+      end
+      
+
+      def matches?(name)
+        !(matches = name.match(@expression)).nil?
+      end
+            
+      def parse_args(name)
+        name.match(@expression)[1..-1]
+      end
+
+      private
+      
+        def assign_expression(string_or_regexp)
+          if String === string_or_regexp
+            expression = string_or_regexp.dup
+            expression.gsub! '(', '\('
+            expression.gsub! ')', '\)'
+          elsif Regexp === string_or_regexp
+            expression = string_or_regexp.source
+          end
+          while expression =~ PARAM_PATTERN
+            expression.gsub!($1, "(.*?)")
+          end
+          @expression = Regexp.new("^#{expression}$")
+        end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/lib/spec/story/step_group.rb b/vendor/gems/rspec/lib/spec/story/step_group.rb
new file mode 100644
index 0000000..cae558c
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/step_group.rb
@@ -0,0 +1,89 @@
+module Spec
+  module Story
+
+    class StepGroupHash < Hash
+      def initialize
+        super do |h,k|
+          h[k] = Spec::Story::StepGroup.new
+        end
+      end
+    end
+
+    class StepGroup
+      def self.steps(&block)
+        @step_group ||= StepGroup.new(false)
+        @step_group.instance_eval(&block) if block
+        @step_group
+      end
+      
+      def initialize(init_defaults=true, &block)
+        @hash_of_lists_of_steps = Hash.new {|h, k| h[k] = []}
+        if init_defaults
+          self.class.steps.add_to(self)
+        end
+        instance_eval(&block) if block
+      end
+      
+      def find(type, name)
+        @hash_of_lists_of_steps[type].each do |step|
+          return step if step.matches?(name)
+        end
+        return nil
+      end
+
+      def GivenScenario(name, &block)
+        create_matcher(:given_scenario, name, &block)
+      end
+      
+      def Given(name, &block)
+        create_matcher(:given, name, &block)
+      end
+      
+      def When(name, &block)
+        create_matcher(:when, name, &block)
+      end
+      
+      def Then(name, &block)
+        create_matcher(:then, name, &block)
+      end
+
+      alias :given_scenario :GivenScenario
+      alias :given :Given
+      alias :when :When
+      alias :then :Then
+      
+      def add(type, steps)
+        (@hash_of_lists_of_steps[type] << steps).flatten!
+      end
+      
+      def clear
+        @hash_of_lists_of_steps.clear
+      end
+      
+      def empty?
+        [:given_scenario, :given, :when, :then].each do |type|
+          return false unless @hash_of_lists_of_steps[type].empty?
+        end
+        return true
+      end
+      
+      def add_to(other_step_matchers)
+        [:given_scenario, :given, :when, :then].each do |type|
+          other_step_matchers.add(type, @hash_of_lists_of_steps[type])
+        end
+      end
+      
+      def <<(other_step_matchers)
+        other_step_matchers.add_to(self) if other_step_matchers.respond_to?(:add_to)
+      end
+      
+      # TODO - make me private
+      def create_matcher(type, name, &block)
+        matcher = Step.new(name, &block)
+        @hash_of_lists_of_steps[type] << matcher
+        matcher
+      end
+      
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/step_mother.rb b/vendor/gems/rspec/lib/spec/story/step_mother.rb
new file mode 100644
index 0000000..a2e84e3
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/step_mother.rb
@@ -0,0 +1,37 @@
+module Spec
+  module Story
+    class StepMother
+      def initialize
+        @steps = StepGroup.new
+      end
+      
+      def use(new_step_group)
+        @steps << new_step_group
+      end
+      
+      def store(type, step)
+        @steps.add(type, step)
+      end
+      
+      def find(type, name)
+        if @steps.find(type, name).nil?
+          @steps.add(type,
+          Step.new(name) do
+            raise Spec::Example::ExamplePendingError.new("Unimplemented step: #{name}")
+          end
+          )
+        end
+        @steps.find(type, name)
+      end
+      
+      def clear
+        @steps.clear
+      end
+      
+      def empty?
+        @steps.empty?
+      end
+      
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/story.rb b/vendor/gems/rspec/lib/spec/story/story.rb
new file mode 100644
index 0000000..112e941
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/story.rb
@@ -0,0 +1,42 @@
+module Spec
+  module Story
+    class Story
+      attr_reader :title, :narrative
+      
+      def initialize(title, narrative, params = {}, &body)
+        @body = body
+        @title = title
+        @narrative = narrative
+        @params = params
+      end
+      
+      def [](key)
+        @params[key]
+      end
+      
+      def run_in(obj)
+        obj.instance_eval(&@body)
+      end
+      
+      def assign_steps_to(assignee)
+        if @params[:steps]
+          assignee.use(@params[:steps])
+        else
+          case keys = @params[:steps_for]
+          when Symbol
+            keys = [keys]
+          when nil
+            keys = []
+          end
+          keys.each do |key|
+            assignee.use(steps_for(key))
+          end
+        end
+      end
+      
+      def steps_for(key)
+        $rspec_story_steps[key]
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/story/world.rb b/vendor/gems/rspec/lib/spec/story/world.rb
new file mode 100644
index 0000000..93b6e1d
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/story/world.rb
@@ -0,0 +1,125 @@
+require 'rubygems'
+require 'spec/expectations'
+require 'spec/matchers'
+require 'spec/example/pending'
+
+module Spec
+  module Story
+=begin
+  A World represents the actual instance a scenario will run in.
+  
+  The runner ensures any instance variables and methods defined anywhere
+  in a story block are available to all the scenarios. This includes
+  variables that are created or referenced inside Given, When and Then
+  blocks.
+=end
+    module World
+      include ::Spec::Example::Pending
+      include ::Spec::Matchers
+      # store steps and listeners in the singleton metaclass.
+      # This serves both to keep them out of the way of runtime Worlds
+      # and to make them available to all instances.
+      class << self
+        def create(cls = Object, *args)
+          cls.new(*args).extend(World)
+        end
+        
+        def listeners
+          @listeners ||= []
+        end
+        
+        def add_listener(listener)
+          listeners() << listener
+        end
+        
+        def step_mother
+          @step_mother ||= StepMother.new
+        end
+                
+        def use(steps)
+          step_mother.use(steps)
+        end
+        
+        def step_names
+          @step_names ||= []
+        end
+
+        def run_given_scenario_with_suspended_listeners(world, type, name, scenario)
+          current_listeners = Array.new(listeners)
+          begin
+            listeners.each { |l| l.found_scenario(type, name) }
+            @listeners.clear
+            scenario.perform(world, name) unless ::Spec::Story::Runner.dry_run
+          ensure
+            @listeners.replace(current_listeners)
+          end
+        end
+        
+        def store_and_call(world, type, name, *args, &block)
+          if block_given?
+            step_mother.store(type, Step.new(name, &block))
+          end
+          step = step_mother.find(type, name)
+
+          step_name = step.name
+          step_names << step_name
+          
+          # It's important to have access to the parsed args here, so
+          # we can give them to the listeners. The HTML reporter needs
+          # the args so it can style them. See the generated output in
+          # story_server/prototype/rspec_stories.html (generated by rake stories)
+          args = step.parse_args(name) if args.empty?
+          begin
+            listeners.each { |l| l.step_upcoming(type, step_name, *args) }
+            step.perform(world, *args) unless ::Spec::Story::Runner.dry_run
+            listeners.each { |l| l.step_succeeded(type, step_name, *args) }
+          rescue Exception => e
+            case e
+            when Spec::Example::ExamplePendingError
+              @listeners.each { |l| l.step_pending(type, step_name, *args) }
+            else
+              @listeners.each { |l| l.step_failed(type, step_name, *args) }
+            end
+            errors << e
+          end
+        end
+        
+        def errors
+          @errors ||= []
+        end
+      end # end of class << self
+      
+      def start_collecting_errors
+        errors.clear
+      end
+      
+      def errors
+        World.errors
+      end
+      
+      def GivenScenario(name)
+        World.run_given_scenario_with_suspended_listeners(self, :'given scenario', name, GivenScenario.new(name))
+        @__previous_step = :given
+      end
+      
+      def Given(name, *args, &block)
+        World.store_and_call self, :given, name, *args, &block
+        @__previous_step = :given
+      end
+      
+      def When(name, *args, &block)
+        World.store_and_call self, :when, name, *args, &block
+        @__previous_step = :when
+      end
+      
+      def Then(name, *args, &block)
+        World.store_and_call self, :then, name, *args, &block
+        @__previous_step = :then
+      end
+      
+      def And(name, *args, &block)
+        World.store_and_call self, @__previous_step, name, *args, &block
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/translator.rb b/vendor/gems/rspec/lib/spec/translator.rb
new file mode 100644
index 0000000..c1e07ed
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/translator.rb
@@ -0,0 +1,114 @@
+require 'fileutils'
+
+module Spec
+  class Translator
+    def translate(from, to)
+      from = File.expand_path(from)
+      to = File.expand_path(to)
+      if File.directory?(from)
+        translate_dir(from, to)
+      elsif(from =~ /\.rb$/)
+        translate_file(from, to)
+      end
+    end
+    
+    def translate_dir(from, to)
+      FileUtils.mkdir_p(to) unless File.directory?(to)
+      Dir["#{from}/*"].each do |sub_from|
+        path = sub_from[from.length+1..-1]
+        sub_to = File.join(to, path)
+        translate(sub_from, sub_to)
+      end
+    end
+
+    def translate_file(from, to)
+      translation = ""
+      File.open(from) do |io|
+        io.each_line do |line|
+          translation << translate_line(line)
+        end
+      end
+      File.open(to, "w") do |io|
+        io.write(translation)
+      end
+    end
+
+    def translate_line(line)
+      # Translate deprecated mock constraints
+      line.gsub!(/:any_args/, 'any_args')
+      line.gsub!(/:anything/, 'anything')
+      line.gsub!(/:boolean/, 'boolean')
+      line.gsub!(/:no_args/, 'no_args')
+      line.gsub!(/:numeric/, 'an_instance_of(Numeric)')
+      line.gsub!(/:string/, 'an_instance_of(String)')
+
+      return line if line =~ /(should_not|should)_receive/
+      
+      line.gsub!(/(^\s*)context([\s*|\(]['|"|A-Z])/, '\1describe\2')
+      line.gsub!(/(^\s*)specify([\s*|\(]['|"|A-Z])/, '\1it\2')
+      line.gsub!(/(^\s*)context_setup(\s*[do|\{])/, '\1before(:all)\2')
+      line.gsub!(/(^\s*)context_teardown(\s*[do|\{])/, '\1after(:all)\2')
+      line.gsub!(/(^\s*)setup(\s*[do|\{])/, '\1before(:each)\2')
+      line.gsub!(/(^\s*)teardown(\s*[do|\{])/, '\1after(:each)\2')
+      
+      if line =~ /(.*\.)(should_not|should)(?:_be)(?!_)(.*)/m
+        pre = $1
+        should = $2
+        post = $3
+        be_or_equal = post =~ /(<|>)/ ? "be" : "equal"
+        
+        return "#{pre}#{should} #{be_or_equal}#{post}"
+      end
+      
+      if line =~ /(.*\.)(should_not|should)_(?!not)\s*(.*)/m
+        pre = $1
+        should = $2
+        post = $3
+        
+        post.gsub!(/^raise/, 'raise_error')
+        post.gsub!(/^throw/, 'throw_symbol')
+        
+        unless standard_matcher?(post)
+          post = "be_#{post}"
+        end
+        
+        # Add parenthesis
+        post.gsub!(/^(\w+)\s+([\w|\.|\,|\(.*\)|\'|\"|\:|@| ]+)(\})/, '\1(\2)\3') # inside a block
+        post.gsub!(/^(redirect_to)\s+(.*)/, '\1(\2)') # redirect_to, which often has http:
+        post.gsub!(/^(\w+)\s+([\w|\.|\,|\(.*\)|\{.*\}|\'|\"|\:|@| ]+)/, '\1(\2)')
+        post.gsub!(/(\s+\))/, ')')
+        post.gsub!(/\)\}/, ') }')
+        post.gsub!(/^(\w+)\s+(\/.*\/)/, '\1(\2)') #regexps
+        line = "#{pre}#{should} #{post}"
+      end
+
+      line
+    end
+    
+    def standard_matcher?(matcher)
+      patterns = [
+        /^be/, 
+        /^be_close/,
+        /^eql/, 
+        /^equal/, 
+        /^has/, 
+        /^have/, 
+        /^change/, 
+        /^include/,
+        /^match/, 
+        /^raise_error/, 
+        /^respond_to/, 
+        /^redirect_to/, 
+        /^satisfy/, 
+        /^throw_symbol/,
+        # Extra ones that we use in spec_helper
+        /^pass/,
+        /^fail/,
+        /^fail_with/,
+      ]
+      matched = patterns.detect{ |p| matcher =~ p }
+      !matched.nil?
+    end
+    
+  end
+end
diff --git a/vendor/gems/rspec/lib/spec/version.rb b/vendor/gems/rspec/lib/spec/version.rb
new file mode 100644
index 0000000..26c15e9
--- /dev/null
+++ b/vendor/gems/rspec/lib/spec/version.rb
@@ -0,0 +1,22 @@
+module Spec
+  module VERSION
+    unless defined? MAJOR
+      MAJOR  = 1
+      MINOR  = 1
+      TINY   = 3
+      RELEASE_CANDIDATE = nil
+
+      BUILD_TIME_UTC = 20080131122909
+
+      STRING = [MAJOR, MINOR, TINY].join('.')
+      TAG = "REL_#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('_')}".upcase.gsub(/\.|-/, '_')
+      FULL_VERSION = "#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('.')} (build #{BUILD_TIME_UTC})"
+
+      NAME   = "RSpec"
+      URL    = "http://rspec.rubyforge.org/"  
+    
+      DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}"
+    end
+  end
+end
+
diff --git a/vendor/gems/rspec/plugins/mock_frameworks/flexmock.rb b/vendor/gems/rspec/plugins/mock_frameworks/flexmock.rb
new file mode 100644
index 0000000..6875a52
--- /dev/null
+++ b/vendor/gems/rspec/plugins/mock_frameworks/flexmock.rb
@@ -0,0 +1,23 @@
+#!/usr/bin/env ruby
+#
+#  Created by Jim Weirich on 2007-04-10.
+#  Copyright (c) 2007. All rights reserved.
+
+require 'flexmock/rspec'
+
+module Spec
+  module Plugins
+    module MockFramework
+      include FlexMock::MockContainer
+      def setup_mocks_for_rspec
+        # No setup required
+      end
+      def verify_mocks_for_rspec
+        flexmock_verify
+      end
+      def teardown_mocks_for_rspec
+        flexmock_close
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/plugins/mock_frameworks/mocha.rb b/vendor/gems/rspec/plugins/mock_frameworks/mocha.rb
new file mode 100644
index 0000000..69d1163
--- /dev/null
+++ b/vendor/gems/rspec/plugins/mock_frameworks/mocha.rb
@@ -0,0 +1,19 @@
+require 'mocha/standalone'
+require 'mocha/object'
+
+module Spec
+  module Plugins
+    module MockFramework
+      include Mocha::Standalone
+      def setup_mocks_for_rspec
+        mocha_setup
+      end
+      def verify_mocks_for_rspec
+        mocha_verify
+      end
+      def teardown_mocks_for_rspec
+        mocha_teardown
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/plugins/mock_frameworks/rr.rb b/vendor/gems/rspec/plugins/mock_frameworks/rr.rb
new file mode 100644
index 0000000..c019c18
--- /dev/null
+++ b/vendor/gems/rspec/plugins/mock_frameworks/rr.rb
@@ -0,0 +1,21 @@
+require 'rr'
+
+patterns = ::Spec::Runner::QuietBacktraceTweaker::IGNORE_PATTERNS
+patterns.push(RR::Errors::BACKTRACE_IDENTIFIER)
+
+module Spec
+  module Plugins
+    module MockFramework
+      include RR::Extensions::InstanceMethods
+      def setup_mocks_for_rspec
+        RR::Space.instance.reset
+      end
+      def verify_mocks_for_rspec
+        RR::Space.instance.verify_doubles
+      end
+      def teardown_mocks_for_rspec
+        RR::Space.instance.reset
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/plugins/mock_frameworks/rspec.rb b/vendor/gems/rspec/plugins/mock_frameworks/rspec.rb
new file mode 100644
index 0000000..ce215ac
--- /dev/null
+++ b/vendor/gems/rspec/plugins/mock_frameworks/rspec.rb
@@ -0,0 +1,18 @@
+require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "spec", "mocks"))
+
+module Spec
+  module Plugins
+    module MockFramework
+      include Spec::Mocks::ExampleMethods
+      def setup_mocks_for_rspec
+        $rspec_mocks ||= Spec::Mocks::Space.new
+      end
+      def verify_mocks_for_rspec
+        $rspec_mocks.verify_all
+      end
+      def teardown_mocks_for_rspec
+        $rspec_mocks.reset_all
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/pre_commit/lib/pre_commit.rb b/vendor/gems/rspec/pre_commit/lib/pre_commit.rb
new file mode 100644
index 0000000..2f34808
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/lib/pre_commit.rb
@@ -0,0 +1,4 @@
+require "pre_commit/pre_commit"
+require "pre_commit/rspec"
+require "pre_commit/core"
+require "pre_commit/rspec_on_rails"
diff --git a/vendor/gems/rspec/pre_commit/lib/pre_commit/core.rb b/vendor/gems/rspec/pre_commit/lib/pre_commit/core.rb
new file mode 100644
index 0000000..420cc0c
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/lib/pre_commit/core.rb
@@ -0,0 +1,50 @@
+class PreCommit::Core < PreCommit
+  def pre_commit
+    rake_invoke :examples
+    website
+  end
+
+  def website(run_webby=true)
+    clobber
+    rake_invoke :verify_rcov
+    rake_invoke :spec_html
+    webby
+    rake_invoke :failing_examples_with_html
+    rdoc
+    rdoc_rails
+  end
+
+  def clobber
+    rm_rf '../doc/output'
+    rm_rf 'translated_specs'
+  end
+
+  def webby
+    Dir.chdir '../doc' do
+      output = silent_sh('rake rebuild 2>&1')
+      if shell_error?(output)
+        raise "ERROR while generating web site: #{output}"
+      end
+
+      spec_page = File.expand_path('output/documentation/tools/spec.html')
+      spec_page_content = File.open(spec_page).read
+      unless spec_page_content =~/\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\./m
+        raise "#{'!'*400}\nIt seems like the output in the generated documentation is broken (no dots: ......)\n. Look in #{spec_page}"
+      end
+    end
+  end
+
+  def rdoc
+    Dir.chdir '../rspec' do
+      rake = (PLATFORM == "i386-mswin32") ? "rake.cmd" : "rake"
+      `#{rake} rdoc`
+    end
+  end
+
+  def rdoc_rails
+    Dir.chdir '../rspec_on_rails' do
+      rake = (PLATFORM == "i386-mswin32") ? "rake.cmd" : "rake"
+      `#{rake} rdoc`
+    end
+  end
+end
diff --git a/vendor/gems/rspec/pre_commit/lib/pre_commit/pre_commit.rb b/vendor/gems/rspec/pre_commit/lib/pre_commit/pre_commit.rb
new file mode 100644
index 0000000..80f958b
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/lib/pre_commit/pre_commit.rb
@@ -0,0 +1,54 @@
+class PreCommit
+  attr_reader :actor
+  def initialize(actor)
+    @actor = actor
+  end
+
+  protected
+  def rake_invoke(task_name)
+    Rake::Task[task_name].invoke
+  end
+
+  def rake_sh(task_name, env_hash={})
+    env = env_hash.collect{|key, value| "#{key}=#{value}"}.join(' ')
+    rake = (PLATFORM == "i386-mswin32") ? "rake.bat" : "rake"
+    cmd = "#{rake} #{task_name} #{env} --trace"
+    output = silent_sh(cmd)
+    puts output
+    if shell_error?(output)
+      raise "ERROR while running rake: #{cmd}"
+    end
+  end
+
+  def silent_sh(cmd, &block)
+    output = nil
+    IO.popen(cmd) do |io|
+      output = io.read
+      output.each_line do |line|
+        block.call(line) if block
+      end
+    end
+    output
+  end
+
+  def shell_error?(output)
+    output =~ /ERROR/n || error_code?
+  end
+
+  def error_code?
+    $?.exitstatus != 0
+  end
+
+  def root_dir
+    dir = File.dirname(__FILE__)
+    File.expand_path("#{dir}/../../../..")
+  end  
+
+  def method_missing(method_name, *args, &block)
+    if actor.respond_to?(method_name)
+      actor.send(method_name, *args, &block)
+    else
+      super
+    end
+  end
+end
diff --git a/vendor/gems/rspec/pre_commit/lib/pre_commit/rspec.rb b/vendor/gems/rspec/pre_commit/lib/pre_commit/rspec.rb
new file mode 100644
index 0000000..5078c72
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/lib/pre_commit/rspec.rb
@@ -0,0 +1,111 @@
+class PreCommit::Rspec < PreCommit
+  def pre_commit
+    check_for_gem_dependencies
+    fix_cr_lf
+    touch_revision_storing_files
+    pre_commit_core
+    pre_commit_textmate_bundle
+    pre_commit_rails
+    ok_to_commit
+  end
+  
+  def check_for_gem_dependencies
+    require "rubygems"
+    gem 'rake'
+    gem 'webby'
+    gem 'coderay'
+    gem 'RedCloth'
+    gem 'syntax'
+    gem 'diff-lcs'
+    gem 'heckle' unless PLATFORM == "i386-mswin32"
+    gem 'hpricot'
+  end
+
+  def fix_cr_lf
+    files = FileList['**/*.rb'].
+            exclude('example_rails_app/vendor/**').
+            exclude('rspec/translated_specs/**')
+    $\="\n"
+    files.each do |f|
+      raw_content = File.read(f)
+      fixed_content = ""
+      raw_content.each_line do |line|
+        fixed_content << line
+      end
+      unless raw_content == fixed_content
+        File.open(f, "w") do |io|
+          io.print fixed_content
+        end
+      end
+    end
+  end
+  
+  # TODO - move me up to the project root
+  def touch_revision_storing_files
+    files = [
+      'rspec/lib/spec/version.rb',
+      'rspec_on_rails/lib/spec/rails/version.rb'
+    ]
+    build_time_utc = Time.now.utc.strftime('%Y%m%d%H%M%S')
+    files.each do |path|
+      abs_path = File.join(root_dir, path)
+      content = File.open(abs_path).read
+      touched_content = content.gsub(/BUILD_TIME_UTC = (\d*)/, "BUILD_TIME_UTC = #{build_time_utc}")
+      File.open(abs_path, 'w') do |io|
+        io.write touched_content
+      end
+    end
+  end
+  
+  def pre_commit_core
+    Dir.chdir 'rspec' do
+      rake = (PLATFORM == "i386-mswin32") ? "rake.bat" : "rake"
+      system("#{rake} pre_commit --verbose --trace")
+      raise "RSpec Core pre_commit failed" if error_code?
+    end    
+  end
+
+  def pre_commit_textmate_bundle
+    Dir.chdir 'RSpec.tmbundle/Support' do
+      rake = (PLATFORM == "i386-mswin32") ? "rake.bat" : "rake"
+      system("#{rake} spec --verbose --trace")
+      raise "RSpec Textmate Bundle specs failed" if error_code?
+    end    
+  end
+
+  def install_dependencies
+    Dir.chdir 'example_rails_app' do
+      rake_sh("-f Multirails.rake install_dependencies")
+    end
+  end
+
+  def update_dependencies
+    Dir.chdir 'example_rails_app' do
+      rake_sh("-f Multirails.rake update_dependencies")
+    end
+  end
+
+  def pre_commit_rails
+    Dir.chdir 'example_rails_app' do
+      rake = (PLATFORM == "i386-mswin32") ? "rake.cmd" : "rake"
+      cmd = "#{rake} -f Multirails.rake pre_commit --trace"
+      system(cmd)
+      if error_code?
+        message = <<-EOF
+        ############################################################
+        RSpec on Rails Plugin pre_commit failed. For more info:
+
+          cd example_rails_app
+          #{cmd}
+
+        ############################################################
+        EOF
+        raise message.gsub(/^        /, '')
+      end
+    end
+  end
+  
+  def ok_to_commit
+    puts "OK TO COMMIT"
+  end
+end
diff --git a/vendor/gems/rspec/pre_commit/lib/pre_commit/rspec_on_rails.rb b/vendor/gems/rspec/pre_commit/lib/pre_commit/rspec_on_rails.rb
new file mode 100644
index 0000000..7879537
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/lib/pre_commit/rspec_on_rails.rb
@@ -0,0 +1,313 @@
+class PreCommit::RspecOnRails < PreCommit
+  def pre_commit
+    install_plugins
+    check_dependencies
+    used_railses = []
+    VENDOR_DEPS.each do |dependency|
+      rails_dir = File.expand_path(dependency[:checkout_path])
+      rails_version = rails_version_from_dir(rails_dir)
+      begin
+        rspec_pre_commit(rails_version, false)
+        used_railses << rails_version
+      rescue Exception => e
+        unless rails_version == 'edge'
+          raise e
+        end
+      end
+    end
+    uninstall_plugins
+    puts "All specs passed against the following released versions of Rails: #{used_railses.join(", ")}"
+    unless used_railses.include?('edge')
+      puts "There were errors running pre_commit against edge"
+    end
+  end
+
+  def rails_version_from_dir(rails_dir)
+    File.basename(rails_dir)
+  end
+
+  def rspec_pre_commit(rails_version=ENV['RSPEC_RAILS_VERSION'],uninstall=true)
+    puts "#####################################################"
+    puts "running pre_commit against rails #{rails_version}"
+    puts "#####################################################"
+    ENV['RSPEC_RAILS_VERSION'] = rails_version
+    cleanup(uninstall)
+    ensure_db_config
+    clobber_sqlite_data
+    install_plugins
+    generate_rspec
+
+    generate_login_controller
+    create_purchase
+
+    rake_sh "spec"
+    rake_sh "spec:plugins:rspec_on_rails"
+    
+    # TODO - why is this necessary? Shouldn't the specs leave
+    # a clean DB?
+    rake_sh "db:test:prepare"
+    sh "ruby vendor/plugins/rspec_on_rails/stories/all.rb"
+    cleanup(uninstall)
+  end
+
+  def cleanup(uninstall=true)
+    revert_routes
+    rm_generated_login_controller_files
+    destroy_purchase
+    uninstall_plugins if uninstall
+  end
+
+  def revert_routes
+    output = silent_sh("cp config/routes.rb.bak config/routes.rb")
+    raise "Error reverting routes.rb" if shell_error?(output)
+  end
+
+  def create_purchase
+    generate_purchase
+    migrate_up
+  end
+
+  def install_plugins
+    install_rspec_on_rails_plugin
+    install_rspec_plugin
+  end
+
+  def install_rspec_on_rails_plugin
+    rm_rf 'vendor/plugins/rspec_on_rails'
+    copy '../rspec_on_rails', 'vendor/plugins/'
+  end
+
+  def install_rspec_plugin
+    rm_rf 'vendor/plugins/rspec'
+    copy '../rspec', 'vendor/plugins/'
+  end
+
+  def uninstall_plugins
+    rm_rf 'vendor/plugins/rspec_on_rails'
+    rm_rf 'vendor/plugins/rspec'
+    rm_rf 'script/spec'
+    rm_rf 'script/spec_server'
+    rm_rf 'spec/spec_helper.rb'
+    rm_rf 'spec/spec.opts'
+    rm_rf 'spec/rcov.opts'
+  end
+  
+  def copy(source, target)
+    output = silent_sh("cp -R #{File.expand_path(source)} #{File.expand_path(target)}")
+    raise "Error installing rspec" if shell_error?(output)
+  end
+  
+  def generate_rspec
+    result = silent_sh("ruby script/generate rspec --force")
+    if error_code? || result =~ /^Missing/
+      raise "Failed to generate rspec environment:\n#{result}"
+    end
+  end
+
+  def ensure_db_config
+    config_path = 'config/database.yml'
+    unless File.exists?(config_path)
+      message = <<-EOF
+      #####################################################
+      Could not find #{config_path}
+
+      You can get rake to generate this file for you using either of:
+        rake rspec:generate_mysql_config
+        rake rspec:generate_sqlite3_config
+
+      If you use mysql, you'll need to create dev and test
+      databases and users for each. To do this, standing
+      in rspec_on_rails, log into mysql as root and then...
+        mysql> source db/mysql_setup.sql;
+
+      There is also a teardown script that will remove
+      the databases and users:
+        mysql> source db/mysql_teardown.sql;
+      #####################################################
+      EOF
+      raise message.gsub(/^      /, '')
+    end
+  end
+
+  def generate_mysql_config
+    copy 'config/database.mysql.yml', 'config/database.yml'
+  end
+
+  def generate_sqlite3_config
+    copy 'config/database.sqlite3.yml', 'config/database.yml'
+  end
+
+  def clobber_db_config
+    rm 'config/database.yml'
+  end
+
+  def clobber_sqlite_data
+    rm_rf 'db/*.db'
+  end
+
+  def generate_purchase
+    generator = "ruby script/generate rspec_scaffold purchase order_id:integer created_at:datetime amount:decimal keyword:string description:text --force"
+    notice = <<-EOF
+    #####################################################
+    #{generator}
+    #####################################################
+    EOF
+    puts notice.gsub(/^    /, '')
+    result = silent_sh(generator)
+    if error_code? || result =~ /not/
+      raise "rspec_scaffold failed. #{result}"
+    end
+  end
+  
+  def purchase_migration_version
+    "005"
+  end
+
+  def migrate_up
+    rake_sh "db:migrate"
+  end
+
+  def destroy_purchase
+    migrate_down
+    rm_generated_purchase_files
+  end
+
+  def migrate_down
+    notice = <<-EOF
+    #####################################################
+    Migrating down and reverting config/routes.rb
+    #####################################################
+    EOF
+    puts notice.gsub(/^    /, '')
+    rake_sh "db:migrate", 'VERSION' => (purchase_migration_version.to_i - 1)
+    output = silent_sh("cp config/routes.rb.bak config/routes.rb")
+    raise "revert failed: #{output}" if error_code?
+  end
+
+  def rm_generated_purchase_files
+    puts "#####################################################"
+    puts "Removing generated files:"
+    generated_files = %W{
+      app/helpers/purchases_helper.rb
+      app/models/purchase.rb
+      app/controllers/purchases_controller.rb
+      app/views/purchases
+      db/migrate/#{purchase_migration_version}_create_purchases.rb
+      spec/models/purchase_spec.rb
+      spec/helpers/purchases_helper_spec.rb
+      spec/controllers/purchases_controller_spec.rb
+      spec/controllers/purchases_routing_spec.rb
+      spec/fixtures/purchases.yml
+      spec/views/purchases
+    }
+    generated_files.each do |file|
+      rm_rf file
+    end
+    puts "#####################################################"
+  end
+  
+  def generate_login_controller
+    generator = "ruby script/generate rspec_controller login signup login logout --force"
+    notice = <<-EOF
+    #####################################################
+    #{generator}
+    #####################################################
+    EOF
+    puts notice.gsub(/^    /, '')
+    result = silent_sh(generator)
+    if error_code? || result =~ /not/
+      raise "rspec_scaffold failed. #{result}"
+    end
+  end
+
+  def rm_generated_login_controller_files
+    puts "#####################################################"
+    puts "Removing generated files:"
+    generated_files = %W{
+      app/helpers/login_helper.rb
+      app/controllers/login_controller.rb
+      app/views/login
+      spec/helpers/login_helper_spec.rb
+      spec/controllers/login_controller_spec.rb
+      spec/views/login
+    }
+    generated_files.each do |file|
+      rm_rf file
+    end
+    puts "#####################################################"
+  end
+
+  def install_dependencies
+    VENDOR_DEPS.each do |dep|
+      puts "\nChecking for #{dep[:name]} ..."
+      dest = dep[:checkout_path]
+      if File.exists?(dest)
+        puts "#{dep[:name]} already installed"
+      else
+        cmd = "svn co #{dep[:url]} #{dest}"
+        puts "Installing #{dep[:name]}"
+        puts "This may take a while."
+        puts cmd
+        system(cmd)
+        puts "Done!"
+      end
+    end
+    puts
+  end
+
+  def check_dependencies
+    VENDOR_DEPS.each do |dep|
+      unless File.exist?(dep[:checkout_path])
+        raise "There is no checkout of #{dep[:checkout_path]}. Please run rake install_dependencies"
+      end
+      # Verify that the current working copy is right
+      if `svn info #{dep[:checkout_path]}` =~ /^URL: (.*)/
+        actual_url = $1
+        if actual_url != dep[:url]
+          raise "Your working copy in #{dep[:checkout_path]} points to \n#{actual_url}\nIt has moved to\n#{dep[:url]}\nPlease delete the working copy and run rake install_dependencies"
+        end
+      end
+    end
+  end
+  
+  def update_dependencies
+    check_dependencies
+    VENDOR_DEPS.each do |dep|
+      next if dep[:tagged?] #
+      puts "\nUpdating #{dep[:name]} ..."
+      dest = dep[:checkout_path]
+      system("svn cleanup #{dest}")
+      cmd = "svn up #{dest}"
+      puts cmd
+      system(cmd)
+      puts "Done!"
+    end
+  end
+
+  VENDOR_DEPS = [
+    {
+      :checkout_path => "vendor/rails/2.0.2",
+      :name =>  "rails 2.0.2",
+      :url => "http://dev.rubyonrails.org/svn/rails/tags/rel_2-0-2",
+      :tagged? => true
+    },
+    {
+      :checkout_path => "vendor/rails/1.2.6",
+      :name =>  "rails 1.2.6",
+      :url => "http://dev.rubyonrails.org/svn/rails/tags/rel_1-2-6",
+      :tagged? => true
+    },
+    {
+      :checkout_path => "vendor/rails/1.2.3",
+      :name =>  "rails 1.2.3",
+      :url => "http://dev.rubyonrails.org/svn/rails/tags/rel_1-2-3",
+      :tagged? => true
+    },
+    {
+      :checkout_path => "vendor/rails/edge",
+      :name =>  "edge rails",
+      :url => "http://svn.rubyonrails.org/rails/trunk",
+      :tagged? => false
+    }
+  ]
+end
diff --git a/vendor/gems/rspec/pre_commit/spec/pre_commit/pre_commit_spec.rb b/vendor/gems/rspec/pre_commit/spec/pre_commit/pre_commit_spec.rb
new file mode 100644
index 0000000..5d1c8f9
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/spec/pre_commit/pre_commit_spec.rb
@@ -0,0 +1,15 @@
+require File.dirname(__FILE__) + '/../spec_helper.rb'
+
+##
+# This is not a complete specification of PreCommit, but 
+# just a collection of bug fix regression tests.
+describe "The helper method PreCommit#silent_sh" do
+  before do
+    @pre_commit = PreCommit.new(nil)
+  end
+
+  # bug in r1802
+  it "should return the command output" do
+    @pre_commit.send(:silent_sh, "echo foo").should ==("foo\n")
+  end
+end
diff --git a/vendor/gems/rspec/pre_commit/spec/pre_commit/rspec_on_rails_spec.rb b/vendor/gems/rspec/pre_commit/spec/pre_commit/rspec_on_rails_spec.rb
new file mode 100644
index 0000000..1932fff
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/spec/pre_commit/rspec_on_rails_spec.rb
@@ -0,0 +1,36 @@
+require File.dirname(__FILE__) + '/../spec_helper.rb'
+require 'fileutils'
+
+include FileUtils
+
+##
+# This is not a complete specification of PreCommit.RSpecOnRails, but 
+# just a collection of bug fix regression tests.
+describe "RSpecOnRails pre_commit" do
+  before do
+    @original_dir = File.expand_path(FileUtils.pwd)
+    @rails_app_dir = File.expand_path(File.dirname(__FILE__) + "/../../../example_rails_app/")
+
+    Dir.chdir(@rails_app_dir)
+    rm_rf('vendor/plugins/rspec_on_rails')
+    system("svn export ../rspec_on_rails vendor/plugins/rspec_on_rails")
+
+    @pre_commit = PreCommit::RspecOnRails.new(nil)
+  end
+
+  after do
+    rm('db/migrate/888_create_purchases.rb', :force => true)
+    @pre_commit.destroy_purchase
+    Dir.chdir(@original_dir)
+  end
+
+  # bug in r1802
+  it "should fail noisily if there is a migration name conflict" do
+    touch('db/migrate/888_create_purchases.rb')
+    lambda { @pre_commit.generate_purchase }.should raise_error
+  end
+
+  it "should not fail if tests run ok" do
+    lambda { @pre_commit.generate_purchase }.should_not raise_error
+  end
+end
diff --git a/vendor/gems/rspec/pre_commit/spec/spec_helper.rb b/vendor/gems/rspec/pre_commit/spec/spec_helper.rb
new file mode 100644
index 0000000..b7e5f3d
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/spec/spec_helper.rb
@@ -0,0 +1,3 @@
+$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
+require 'pre_commit'
+
diff --git a/vendor/gems/rspec/pre_commit/spec/spec_suite.rb b/vendor/gems/rspec/pre_commit/spec/spec_suite.rb
new file mode 100644
index 0000000..a8c7c07
--- /dev/null
+++ b/vendor/gems/rspec/pre_commit/spec/spec_suite.rb
@@ -0,0 +1,11 @@
+class SpecSuite
+  def run
+    system("ruby rspec/spec/rspec_suite.rb") || raise("Rspec Suite FAILED")
+    system("ruby rspec_on_rails/spec/rails_suite.rb") || raise("Rails Suite FAILED")
+    system("ruby cached_example_rails_app/spec/rails_app_suite.rb") || raise("Rails App Suite FAILED")
+  end
+end
+
+if $0 == __FILE__
+  SpecSuite.new.run
+end
diff --git a/vendor/gems/rspec/rake_tasks/examples.rake b/vendor/gems/rspec/rake_tasks/examples.rake
new file mode 100644
index 0000000..32d0ad0
--- /dev/null
+++ b/vendor/gems/rspec/rake_tasks/examples.rake
@@ -0,0 +1,7 @@
+require 'rake'
+require 'spec/rake/spectask'
+
+desc "Run all examples"
+Spec::Rake::SpecTask.new('examples') do |t|
+  t.spec_files = FileList['examples/**/*.rb']
+end
diff --git a/vendor/gems/rspec/rake_tasks/examples_with_rcov.rake b/vendor/gems/rspec/rake_tasks/examples_with_rcov.rake
new file mode 100644
index 0000000..4bf35c6
--- /dev/null
+++ b/vendor/gems/rspec/rake_tasks/examples_with_rcov.rake
@@ -0,0 +1,9 @@
+require 'rake'
+require 'spec/rake/spectask'
+
+desc "Run all examples with RCov"
+Spec::Rake::SpecTask.new('examples_with_rcov') do |t|
+  t.spec_files = FileList['examples/**/*.rb']
+  t.rcov = true
+  t.rcov_opts = ['--exclude', 'examples']
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/rake_tasks/failing_examples_with_html.rake b/vendor/gems/rspec/rake_tasks/failing_examples_with_html.rake
new file mode 100644
index 0000000..3454958
--- /dev/null
+++ b/vendor/gems/rspec/rake_tasks/failing_examples_with_html.rake
@@ -0,0 +1,9 @@
+require 'rake'
+require 'spec/rake/spectask'
+
+desc "Generate HTML report for failing examples"
+Spec::Rake::SpecTask.new('failing_examples_with_html') do |t|
+  t.spec_files = FileList['failing_examples/**/*.rb']
+  t.spec_opts = ["--format", "html:../doc/output/documentation/tools/failing_examples.html", "--diff"]
+  t.fail_on_error = false
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/rake_tasks/verify_rcov.rake b/vendor/gems/rspec/rake_tasks/verify_rcov.rake
new file mode 100644
index 0000000..a90a266
--- /dev/null
+++ b/vendor/gems/rspec/rake_tasks/verify_rcov.rake
@@ -0,0 +1,7 @@
+require 'rake'
+require 'spec/rake/verify_rcov'
+
+RCov::VerifyTask.new(:verify_rcov => :spec) do |t|
+  t.threshold = 100.0 # Make sure you have rcov 0.7 or higher!
+  t.index_html = '../doc/output/coverage/index.html'
+end
diff --git a/vendor/gems/rspec/spec/README.jruby b/vendor/gems/rspec/spec/README.jruby
new file mode 100644
index 0000000..7eddb56
--- /dev/null
+++ b/vendor/gems/rspec/spec/README.jruby
@@ -0,0 +1,15 @@
+= Running specs on JRuby =
+
+svn co http://svn.codehaus.org/jruby/trunk jruby
+cd jruby/jruby
+ant clean
+ant
+# put JRuby's bin dir on your PATH
+jruby -S gem install rake --no-ri --no-rdoc
+jruby -S gem install diff-lcs
+jruby -S gem install syntax
+cd ../testsuites/rspec
+mkdir target
+jruby -S rake checkout_code
+cd target/rspec
+jruby bin/spec spec -c
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 0000000..da5cb14
--- /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 0000000..67ee7fb
--- /dev/null
+++ b/vendor/gems/rspec/spec/autotest/rspec_spec.rb
@@ -0,0 +1,195 @@
+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 == [
+        File.expand_path("#{File.dirname(__FILE__)}/../../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
+    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
+
+      spec_path = File.expand_path("#{File.dirname(__FILE__)}/../../bin/spec")
+      File.should_receive(:exists?).with(spec_path).and_return true
+      @rspec_autotest.spec_command.should == spec_path
+    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
+      spec_command = File.expand_path("#{File.dirname(__FILE__)}/../../bin/spec")
+      @rspec_autotest.stub!(:spec_commands).and_return [spec_command]
+      @rspec_autotest.spec_command(@windows_alt_separator).should == spec_command.gsub('/', @windows_alt_separator)
+    end
+    
+    it "should not use the ALT_SEPATOR if it is nil" do
+      @windows_alt_separator = nil
+      @rspec_autotest = Rspec.new
+      spec_command = File.expand_path("#{File.dirname(__FILE__)}/../../bin/spec")
+      @rspec_autotest.stub!(:spec_commands).and_return [spec_command]
+      @rspec_autotest.spec_command.should == spec_command
+    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, "mappings" do
+    
+    before(:each) do
+      @lib_file = "lib/something.rb"
+      @spec_file = "spec/something_spec.rb"
+      @rspec_autotest = Rspec.new
+      @rspec_autotest.hook :initialize
+    end
+    
+    it "should find the spec file for a given lib file" do
+      @rspec_autotest.should map_specs([@spec_file]).to(@lib_file)
+    end
+    
+    it "should find the spec file if given a spec file" do
+      @rspec_autotest.should map_specs([@spec_file]).to(@spec_file)
+    end
+    
+    it "should only find the file if the file is being tracked (in @file)"  do
+      @rspec_autotest.should map_specs([]).to("lib/untracked_file")
+    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.consolidate_failures([[]]).should == {}
+    end
+    
+    it "should return a hash with the spec filename => spec name for each failure or error" do
+      @rspec_autotest.stub!(:test_files_for).and_return "./spec/autotest/rspec_spec.rb"
+      foo = [
+        [
+          "false should be false", 
+          "expected: true,\n     got: false (using ==)\n./spec/autotest/rspec_spec.rb:203:"
+        ]
+      ]
+      @rspec_autotest.consolidate_failures(foo).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 0000000..1b6c600
--- /dev/null
+++ b/vendor/gems/rspec/spec/autotest_helper.rb
@@ -0,0 +1,6 @@
+require "rubygems"
+require 'autotest'
+dir = File.dirname(__FILE__)
+require "#{dir}/spec_helper"
+require File.expand_path("#{dir}/../lib/autotest/rspec")
+require "#{dir}/autotest_matchers"
diff --git a/vendor/gems/rspec/spec/autotest_matchers.rb b/vendor/gems/rspec/spec/autotest_matchers.rb
new file mode 100644
index 0000000..5e23452
--- /dev/null
+++ b/vendor/gems/rspec/spec/autotest_matchers.rb
@@ -0,0 +1,47 @@
+module Spec
+  module Matchers
+    class AutotestMappingMatcher
+      def initialize(specs)
+        @specs = specs
+      end
+  
+      def to(file)
+        @file = file
+        self
+      end
+  
+      def matches?(autotest)
+        @autotest = prepare autotest
+        @actual = autotest.test_files_for(@file)
+        @actual == @specs
+      end
+  
+      def failure_message
+        "expected #{@autotest.class} to map #{@specs.inspect} to #{@file.inspect}\ngot #{@actual.inspect}"
+      end
+  
+      private
+      def prepare autotest
+        stub_found_files autotest
+        stub_find_order autotest
+        autotest
+      end
+  
+      def stub_found_files autotest
+        found_files = @specs.inject({}){|h,f| h[f] = Time.at(0)}
+        autotest.stub!(:find_files).and_return(found_files)
+      end
+
+      def stub_find_order autotest
+        find_order = @specs.dup << @file
+        autotest.instance_eval { @find_order = find_order }
+      end
+
+    end
+    
+    def map_specs(specs)
+      AutotestMappingMatcher.new(specs)
+    end
+    
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/rspec_suite.rb b/vendor/gems/rspec/spec/rspec_suite.rb
new file mode 100644
index 0000000..abd016a
--- /dev/null
+++ b/vendor/gems/rspec/spec/rspec_suite.rb
@@ -0,0 +1,7 @@
+if __FILE__ == $0
+  dir = File.dirname(__FILE__)
+  Dir["#{dir}/**/*_spec.rb"].reverse.each do |file|
+#    puts "require '#{file}'"
+    require file
+  end
+end
diff --git a/vendor/gems/rspec/spec/ruby_forker.rb b/vendor/gems/rspec/spec/ruby_forker.rb
new file mode 100644
index 0000000..6ab0387
--- /dev/null
+++ b/vendor/gems/rspec/spec/ruby_forker.rb
@@ -0,0 +1,13 @@
+require 'rbconfig'
+
+module RubyForker
+  # Forks a ruby interpreter with same type as ourself.
+  # juby will fork jruby, ruby will fork ruby etc.
+  def ruby(args, stderr=nil)
+    config       = ::Config::CONFIG
+    interpreter  = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
+    cmd = "#{interpreter} #{args}"
+    cmd << " 2> #{stderr}" unless stderr.nil?
+    `#{cmd}`
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec.opts b/vendor/gems/rspec/spec/spec.opts
new file mode 100644
index 0000000..48e51f9
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec.opts
@@ -0,0 +1,6 @@
+--colour
+--format
+profile
+--timeout
+20
+--diff
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/example/configuration_spec.rb b/vendor/gems/rspec/spec/spec/example/configuration_spec.rb
new file mode 100755
index 0000000..5b4a604
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/configuration_spec.rb
@@ -0,0 +1,282 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Example
+    
+    describe Configuration do
+      before(:each) do
+        @config = Configuration.new
+        @example_group = mock("example_group")
+      end
+      
+      describe "#mock_with" do
+
+        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
+      end
+
+      describe "#include" do
+
+        before do
+          @original_configuration = Spec::Runner.configuration
+          spec_configuration = @config
+          Spec::Runner.instance_eval {@configuration = spec_configuration}
+          @example_group_class = Class.new(ExampleGroup) do
+            class << self
+              def this_class_has_special_methods
+              end
+            end
+          end
+          ExampleGroupFactory.register(:foobar, @example_group_class)
+        end
+
+        after do
+          original_configuration = @original_configuration
+          Spec::Runner.instance_eval {@configuration = original_configuration}
+          ExampleGroupFactory.reset
+        end
+
+        it "should include the submitted module in ExampleGroup subclasses" do
+          mod = Module.new
+          @config.include mod
+          Class.new(@example_group_class).included_modules.should include(mod)
+        end
+
+        it "should let you define modules to be included for a specific type" do
+          mod = Module.new
+          @config.include mod, :type => :foobar
+          Class.new(@example_group_class).included_modules.should include(mod)
+        end
+
+        it "should not include modules in a type they are not intended for" do
+          mod = Module.new
+          @other_example_group_class = Class.new(ExampleGroup)
+          ExampleGroupFactory.register(:baz, @other_example_group_class)
+
+          @config.include mod, :type => :foobar
+
+          Class.new(@other_example_group_class).included_modules.should_not include(mod)
+        end
+
+      end
+    
+    end
+
+    describe Configuration do
+      
+      before(:each) do
+        @config = Configuration.new
+        @special_example_group = Class.new(ExampleGroup)
+        @special_child_example_group = Class.new(@special_example_group)
+        @nonspecial_example_group = Class.new(ExampleGroup)
+        ExampleGroupFactory.register(:special, @special_example_group)
+        ExampleGroupFactory.register(:special_child, @special_child_example_group)
+        ExampleGroupFactory.register(:non_special, @nonspecial_example_group)
+        @example_group = @special_child_example_group.describe "Special Example Group"
+        @unselected_example_group = Class.new(@nonspecial_example_group).describe "Non Special Example Group"
+      end
+
+      after(:each) do
+        ExampleGroupFactory.reset
+      end
+
+      describe "#prepend_before" do
+        it "prepends the before block on all instances of the passed in type" do
+          order = []
+          @config.prepend_before(:all) do
+            order << :prepend__before_all
+          end
+          @config.prepend_before(:all, :type => :special) do
+            order << :special_prepend__before_all
+          end
+          @config.prepend_before(:all, :type => :special_child) do
+            order << :special_child_prepend__before_all
+          end
+          @config.prepend_before(:each) do
+            order << :prepend__before_each
+          end
+          @config.prepend_before(:each, :type => :special) do
+            order << :special_prepend__before_each
+          end
+          @config.prepend_before(:each, :type => :special_child) do
+            order << :special_child_prepend__before_each
+          end
+          @config.prepend_before(:all, :type => :non_special) do
+            order << :special_prepend__before_all
+          end
+          @config.prepend_before(:each, :type => :non_special) do
+            order << :special_prepend__before_each
+          end
+          @example_group.it "calls prepend_before" do
+          end
+        
+          @example_group.run
+          order.should == [
+            :prepend__before_all,
+            :special_prepend__before_all,
+            :special_child_prepend__before_all,
+            :prepend__before_each,
+            :special_prepend__before_each,
+            :special_child_prepend__before_each
+          ]
+        end
+      end
+
+      describe "#append_before" do
+
+        it "calls append_before on the type" do
+          order = []
+          @config.append_before(:all) do
+            order << :append_before_all
+          end
+          @config.append_before(:all, :type => :special) do
+            order << :special_append_before_all
+          end
+          @config.append_before(:all, :type => :special_child) do
+            order << :special_child_append_before_all
+          end
+          @config.append_before(:each) do
+            order << :append_before_each
+          end
+          @config.append_before(:each, :type => :special) do
+            order << :special_append_before_each
+          end
+          @config.append_before(:each, :type => :special_child) do
+            order << :special_child_append_before_each
+          end
+          @config.append_before(:all, :type => :non_special) do
+            order << :special_append_before_all
+          end
+          @config.append_before(:each, :type => :non_special) do
+            order << :special_append_before_each
+          end
+          @example_group.it "calls append_before" do
+          end
+
+          @example_group.run
+          order.should == [
+            :append_before_all,
+            :special_append_before_all,
+            :special_child_append_before_all,
+            :append_before_each,
+            :special_append_before_each,
+            :special_child_append_before_each
+          ]
+        end
+      end
+
+      describe "#prepend_after" do
+
+        it "prepends the after block on all instances of the passed in type" do
+          order = []
+          @config.prepend_after(:all) do
+            order << :prepend__after_all
+          end
+          @config.prepend_after(:all, :type => :special) do
+            order << :special_prepend__after_all
+          end
+          @config.prepend_after(:all, :type => :special) do
+            order << :special_child_prepend__after_all
+          end
+          @config.prepend_after(:each) do
+            order << :prepend__after_each
+          end
+          @config.prepend_after(:each, :type => :special) do
+            order << :special_prepend__after_each
+          end
+          @config.prepend_after(:each, :type => :special) do
+            order << :special_child_prepend__after_each
+          end
+          @config.prepend_after(:all, :type => :non_special) do
+            order << :special_prepend__after_all
+          end
+          @config.prepend_after(:each, :type => :non_special) do
+            order << :special_prepend__after_each
+          end
+          @example_group.it "calls prepend_after" do
+          end
+
+          @example_group.run
+          order.should == [
+            :special_child_prepend__after_each,
+            :special_prepend__after_each,
+            :prepend__after_each,
+            :special_child_prepend__after_all,
+            :special_prepend__after_all,
+            :prepend__after_all
+          ]
+        end
+      end
+
+      describe "#append_after" do
+
+        it "calls append_after on the type" do
+          order = []
+          @config.append_after(:all) do
+            order << :append__after_all
+          end
+          @config.append_after(:all, :type => :special) do
+            order << :special_append__after_all
+          end
+          @config.append_after(:all, :type => :special_child) do
+            order << :special_child_append__after_all
+          end
+          @config.append_after(:each) do
+            order << :append__after_each
+          end
+          @config.append_after(:each, :type => :special) do
+            order << :special_append__after_each
+          end
+          @config.append_after(:each, :type => :special_child) do
+            order << :special_child_append__after_each
+          end
+          @config.append_after(:all, :type => :non_special) do
+            order << :non_special_append_after_all
+          end
+          @config.append_after(:each, :type => :non_special) do
+            order << :non_special_append_after_each
+          end
+          @example_group.it "calls append_after" do
+          end
+
+          @example_group.run
+          order.should == [
+            :special_child_append__after_each,
+            :special_append__after_each,
+            :append__after_each,
+            :special_child_append__after_all,
+            :special_append__after_all,
+            :append__after_all
+          ]
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/example/example_group_class_definition_spec.rb b/vendor/gems/rspec/spec/spec/example/example_group_class_definition_spec.rb
new file mode 100644
index 0000000..0b00e13
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_group_class_definition_spec.rb
@@ -0,0 +1,48 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    class ExampleGroupSubclass < ExampleGroup
+      class << self
+        attr_accessor :examples_ran
+      end
+
+      @@klass_variable_set = true
+      CONSTANT = :foobar
+
+      before do
+        @instance_variable = :hello
+      end
+
+      it "should run" do
+        self.class.examples_ran = true
+      end
+
+      it "should have access to instance variables" do
+        @instance_variable.should == :hello
+      end
+
+      it "should have access to class variables" do
+        @@klass_variable_set.should == true
+      end
+
+      it "should have access to constants" do
+        CONSTANT.should == :foobar
+      end
+
+      it "should have access to methods defined in the Example Group" do
+        a_method.should == 22
+      end
+
+      def a_method
+        22
+      end
+    end
+
+    describe ExampleGroupSubclass do
+      it "should run" do
+        ExampleGroupSubclass.examples_ran.should be_true
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/example/example_group_factory_spec.rb b/vendor/gems/rspec/spec/spec/example/example_group_factory_spec.rb
new file mode 100644
index 0000000..3b50011
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_group_factory_spec.rb
@@ -0,0 +1,129 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    describe ExampleGroupFactory, "with :foobar registered as custom type" do
+
+      before do
+        @example_group = Class.new(ExampleGroup)
+        ExampleGroupFactory.register(:foobar, @example_group)
+      end
+
+      after do
+        ExampleGroupFactory.reset
+      end
+
+      it "should #get the default ExampleGroup type when passed nil" do
+        ExampleGroupFactory.get(nil).should == ExampleGroup
+      end
+
+      it "should #get the default ExampleGroup for unregistered non-nil values" do
+        ExampleGroupFactory.get(:does_not_exist).should == ExampleGroup
+      end
+
+      it "should #get custom type for :foobar" do
+        ExampleGroupFactory.get(:foobar).should == @example_group
+      end
+
+      it "should #get the actual type when that is passed in" do
+        ExampleGroupFactory.get(@example_group).should == @example_group
+      end
+
+    end    
+
+    describe ExampleGroupFactory, "#create_example_group" do
+      it "should create a uniquely named class" do
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group("example_group") {}
+        example_group.name.should =~ /Spec::Example::ExampleGroup::Subclass_\d+/
+      end
+
+      it "should create a Spec::Example::Example subclass by default" do
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group("example_group") {}
+        example_group.superclass.should == Spec::Example::ExampleGroup
+      end
+
+      it "should create a Spec::Example::Example when :type => :default" do
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group(
+          "example_group", :type => :default
+        ) {}
+        example_group.superclass.should == Spec::Example::ExampleGroup
+      end
+
+      it "should create a Spec::Example::Example when :type => :default" do
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group(
+          "example_group", :type => :default
+        ) {}
+        example_group.superclass.should == Spec::Example::ExampleGroup
+      end
+
+      it "should create specified type when :type => :something_other_than_default" do
+        klass = Class.new(ExampleGroup) do
+          def initialize(*args, &block); end
+        end
+        Spec::Example::ExampleGroupFactory.register(:something_other_than_default, klass)
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group(
+          "example_group", :type => :something_other_than_default
+        ) {}
+        example_group.superclass.should == klass
+      end
+      
+      it "should create a type indicated by :spec_path" do
+        klass = Class.new(ExampleGroup) do
+          def initialize(*args, &block); end
+        end
+        Spec::Example::ExampleGroupFactory.register(:something_other_than_default, klass)
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group(
+          "example_group", :spec_path => "./spec/something_other_than_default/some_spec.rb"
+        ) {}
+        example_group.superclass.should == klass
+      end
+      
+      it "should create a type indicated by :spec_path (with spec_path generated by caller on windows)" do
+        klass = Class.new(ExampleGroup) do
+          def initialize(*args, &block); end
+        end
+        Spec::Example::ExampleGroupFactory.register(:something_other_than_default, klass)
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group(
+          "example_group", :spec_path => "./spec\\something_other_than_default\\some_spec.rb"
+        ) {}
+        example_group.superclass.should == klass
+      end
+      
+      it "should create and register a Spec::Example::Example if :shared => true" do
+        shared_example_group = Spec::Example::ExampleGroupFactory.create_example_group(
+          "name", :spec_path => '/blah/spec/models/blah.rb', :type => :controller, :shared => true
+        ) {}
+        shared_example_group.should be_an_instance_of(Spec::Example::SharedExampleGroup)
+        SharedExampleGroup.shared_example_groups.should include(shared_example_group)
+      end
+
+      it "should favor the :type over the :spec_path" do
+        klass = Class.new(ExampleGroup) do
+          def initialize(*args, &block); end
+        end
+        Spec::Example::ExampleGroupFactory.register(:something_other_than_default, klass)
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group(
+          "name", :spec_path => '/blah/spec/models/blah.rb', :type => :something_other_than_default
+        ) {}
+        example_group.superclass.should == klass
+      end
+
+      it "should register ExampleGroup by default" do
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group("The ExampleGroup") do
+        end
+        rspec_options.example_groups.should include(example_group)
+      end
+
+      it "should enable unregistering of ExampleGroups" do
+        example_group = Spec::Example::ExampleGroupFactory.create_example_group("The ExampleGroup") do
+          unregister
+        end
+        rspec_options.example_groups.should_not include(example_group)
+      end
+      
+      after(:each) do
+        Spec::Example::ExampleGroupFactory.reset
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/example/example_group_methods_spec.rb b/vendor/gems/rspec/spec/spec/example/example_group_methods_spec.rb
new file mode 100644
index 0000000..2b6d660
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_group_methods_spec.rb
@@ -0,0 +1,489 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    describe 'ExampleGroupMethods' do
+      it_should_behave_like "sandboxed rspec_options"
+      attr_reader :example_group, :result, :reporter
+      before(:each) do
+        options.formatters << mock("formatter", :null_object => true)
+        options.backtrace_tweaker = mock("backtrace_tweaker", :null_object => true)
+        @reporter = FakeReporter.new(@options)
+        options.reporter = reporter
+        @example_group = Class.new(ExampleGroup) do
+          describe("ExampleGroup")
+          it "does nothing"
+        end
+        class << example_group
+          public :include
+        end
+        @result = nil
+      end
+
+      after(:each) do
+        ExampleGroup.reset
+      end
+
+      describe "#describe" do
+        attr_reader :child_example_group
+        before do
+          @child_example_group = @example_group.describe("Another ExampleGroup") do
+            it "should pass" do
+              true.should be_true
+            end
+          end
+        end
+
+        it "should create a subclass of the ExampleGroup when passed a block" do
+          child_example_group.superclass.should == @example_group
+          @options.example_groups.should include(child_example_group)
+        end
+
+        it "should not inherit examples" do
+          child_example_group.examples.length.should == 1
+        end
+      end
+
+      describe "#it" do
+        it "should should create an example instance" do
+          lambda {
+            @example_group.it("")
+          }.should change { @example_group.examples.length }.by(1)
+        end
+      end
+
+      describe "#xit" do
+        before(:each) do
+          Kernel.stub!(:warn)
+        end
+
+        it "should NOT  should create an example instance" do
+          lambda {
+            @example_group.xit("")
+          }.should_not change(@example_group.examples, :length)
+        end
+
+        it "should warn that it is disabled" do
+          Kernel.should_receive(:warn).with("Example disabled: foo")
+          @example_group.xit("foo")
+        end
+      end
+
+      describe "#examples" do
+        it "should have Examples" do
+          example_group = Class.new(ExampleGroup) do
+            describe('example')
+            it "should pass" do
+              1.should == 1
+            end
+          end
+          example_group.examples.length.should == 1
+          example_group.examples.first.description.should == "should pass"
+        end
+
+        it "should not include methods that begin with test (only when TU interop is loaded)" do
+          example_group = Class.new(ExampleGroup) do
+            describe('example')
+            def test_any_args(*args)
+              true.should be_true
+            end
+            def test_something
+              1.should == 1
+            end
+            def test
+              raise "This is not a real test"
+            end
+            def testify
+              raise "This is not a real test"
+            end
+          end
+          example_group.examples.length.should == 0
+          example_group.run.should be_true
+        end
+
+        it "should include methods that begin with should and has an arity of 0 in suite" do
+          example_group = Class.new(ExampleGroup) do
+            describe('example')
+            def shouldCamelCase
+              true.should be_true
+            end
+            def should_any_args(*args)
+              true.should be_true
+            end
+            def should_something
+              1.should == 1
+            end
+            def should_not_something
+              1.should_not == 2
+            end
+            def should
+              raise "This is not a real example"
+            end
+            def should_not
+              raise "This is not a real example"
+            end
+          end
+          example_group = example_group.dup
+          example_group.examples.length.should == 4
+          descriptions = example_group.examples.collect {|example| example.description}.sort
+          descriptions.should include("shouldCamelCase")
+          descriptions.should include("should_any_args")
+          descriptions.should include("should_something")
+          descriptions.should include("should_not_something")
+        end
+
+        it "should not include methods that begin with test_ and has an arity > 0 in suite" do
+          example_group = Class.new(ExampleGroup) do
+            describe('example')
+            def test_invalid(foo)
+              1.should == 1
+            end
+            def testInvalidCamelCase(foo)
+              1.should == 1
+            end
+          end
+          example_group.examples.length.should == 0
+        end
+
+        it "should not include methods that begin with should_ and has an arity > 0 in suite" do
+          example_group = Class.new(ExampleGroup) do
+            describe('example')
+            def should_invalid(foo)
+              1.should == 2
+            end
+            def shouldInvalidCamelCase(foo)
+              1.should == 3
+            end
+            def should_not_invalid(foo)
+              1.should == 4
+            end
+            def should_valid
+              1.should == 1
+            end
+          end
+          example_group.examples.length.should == 1
+          example_group.run.should be_true
+        end
+
+        it "should run should_methods" do
+          example_group = Class.new(ExampleGroup) do
+            def should_valid
+              1.should == 2
+            end
+          end
+          example_group.examples.length.should == 1
+          example_group.run.should be_false
+        end
+      end
+
+      describe "#set_description" do
+        attr_reader :example_group
+        before do
+          class << example_group
+            public :set_description
+          end
+        end
+
+        describe "#set_description(String)" do
+          before(:each) do
+            example_group.set_description("abc")
+          end
+
+          specify ".description should return the String passed into .set_description" do
+            example_group.description.should == "abc"
+          end
+
+          specify ".described_type should provide nil as its type" do
+            example_group.described_type.should be_nil
+          end
+        end
+
+        describe "#set_description(Type)" do
+          before(:each) do
+            example_group.set_description(ExampleGroup)
+          end
+
+          specify ".description should return a String representation of that type (fully qualified) as its name" do
+            example_group.description.should == "Spec::Example::ExampleGroup"
+          end
+
+          specify ".described_type should return the passed in type" do
+            example_group.described_type.should == Spec::Example::ExampleGroup
+          end
+        end
+
+        describe "#set_description(String, Type)" do
+          before(:each) do
+            example_group.set_description("behaving", ExampleGroup)
+          end
+
+          specify ".description should return String then space then Type" do
+            example_group.description.should == "behaving Spec::Example::ExampleGroup"
+          end
+
+          specify ".described_type should return the passed in type" do
+            example_group.described_type.should == Spec::Example::ExampleGroup
+          end
+        end
+
+        describe "#set_description(Type, String not starting with a space)" do
+          before(:each) do
+            example_group.set_description(ExampleGroup, "behaving")
+          end
+
+          specify ".description should return the Type then space then String" do
+            example_group.description.should == "Spec::Example::ExampleGroup behaving"
+          end
+        end
+
+        describe "#set_description(Type, String starting with .)" do
+          before(:each) do
+            example_group.set_description(ExampleGroup, ".behaving")
+          end
+
+          specify ".description should return the Type then String" do
+            example_group.description.should == "Spec::Example::ExampleGroup.behaving"
+          end
+        end
+
+        describe "#set_description(Type, String containing .)" do
+          before(:each) do
+            example_group.set_description(ExampleGroup, "calling a.b")
+          end
+
+          specify ".description should return the Type then space then String" do
+            example_group.description.should == "Spec::Example::ExampleGroup calling a.b"
+          end
+        end
+
+        describe "#set_description(Type, String starting with .)" do
+          before(:each) do
+            example_group.set_description(ExampleGroup, ".behaving")
+          end
+
+          specify "should return the Type then String" do
+            example_group.description.should == "Spec::Example::ExampleGroup.behaving"
+          end
+        end
+
+        describe "#set_description(Type, String containing .)" do
+          before(:each) do
+            example_group.set_description(ExampleGroup, "is #1")
+          end
+
+          specify ".description should return the Type then space then String" do
+            example_group.description.should == "Spec::Example::ExampleGroup is #1"
+          end
+        end
+
+        describe "#set_description(String, Type, String)" do
+          before(:each) do
+            example_group.set_description("A", Hash, "with one entry")
+          end
+
+          specify ".description should return the first String then space then Type then second String" do
+            example_group.description.should == "A Hash with one entry"
+          end
+        end
+
+        describe "#set_description(Hash representing options)" do
+          before(:each) do
+            example_group.set_description(:a => "b", :spec_path => "blah")
+          end
+
+          it ".spec_path should expand the passed in :spec_path option passed into the constructor" do
+            example_group.spec_path.should == File.expand_path("blah")
+          end
+
+          it ".description_options should return all the options passed in" do
+            example_group.description_options.should == {:a => "b", :spec_path => "blah"}
+          end
+
+        end
+      end
+
+      describe "#description" do
+        it "should return the same description instance for each call" do
+          example_group.description.should eql(example_group.description)
+        end
+
+        it "should not add a space when description_text begins with #" do
+          child_example_group = Class.new(example_group) do
+            describe("#foobar", "Does something")
+          end
+          child_example_group.description.should == "ExampleGroup#foobar Does something"
+        end
+
+        it "should not add a space when description_text begins with ." do
+          child_example_group = Class.new(example_group) do
+            describe(".foobar", "Does something")
+          end
+          child_example_group.description.should == "ExampleGroup.foobar Does something"
+        end
+        
+        it "should return the class name if nil" do
+          example_group.set_description(nil)
+          example_group.description.should =~ /Class:/
+        end
+        
+        it "should return the class name if nil" do
+          example_group.set_description("")
+          example_group.description.should =~ /Class:/
+        end
+      end
+
+      describe "#description_parts" do
+        it "should return an Array of the current class description args" do
+          example_group.description_parts.should == [example_group.description]
+        end
+
+        it "should return an Array of the description args from each class in the hierarchy" do
+          child_example_group = Class.new(example_group)
+          child_example_group.describe("Child", ExampleGroup)
+          child_example_group.description.should_not be_empty
+
+          grand_child_example_group = Class.new(child_example_group)
+          grand_child_example_group.describe("GrandChild", ExampleGroup)
+          grand_child_example_group.description.should_not be_empty
+
+          grand_child_example_group.description_parts.should == [
+            "ExampleGroup",
+            "Child",
+            Spec::Example::ExampleGroup,
+            "GrandChild",
+            Spec::Example::ExampleGroup
+          ]
+        end
+      end
+
+      describe "#described_type" do
+        it "should return passed in type" do
+          child_example_group = Class.new(example_group) do
+            describe Object
+          end
+          child_example_group.described_type.should == Object
+        end
+
+        it "should return #described_type of superclass when no passed in type" do
+          parent_example_group = Class.new(ExampleGroup) do
+            describe Object, "#foobar"
+          end
+          child_example_group = Class.new(parent_example_group) do
+            describe "not a type"
+          end
+          child_example_group.described_type.should == Object
+        end
+      end
+
+      describe "#remove_after" do
+        it "should unregister a given after(:each) block" do
+          after_all_ran = false
+          @example_group.it("example") {}
+          proc = Proc.new { after_all_ran = true }
+          ExampleGroup.after(:each, &proc)
+          @example_group.run
+          after_all_ran.should be_true
+
+          after_all_ran = false
+          ExampleGroup.remove_after(:each, &proc)
+          @example_group.run
+          after_all_ran.should be_false
+        end
+      end
+
+      describe "#include" do
+        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
+
+          @example_group.include mod1, mod2
+
+          @example_group.mod1_method
+          @example_group.mod2_method
+          mod1_method_called.should be_true
+          mod2_method_called.should be_true
+        end
+      end
+
+      describe "#number_of_examples" do
+        it "should count number of specs" do
+          proc do
+            @example_group.it("one") {}
+            @example_group.it("two") {}
+            @example_group.it("three") {}
+            @example_group.it("four") {}
+          end.should change {@example_group.number_of_examples}.by(4)
+        end
+      end
+
+      describe "#class_eval" do
+        it "should allow constants to be defined" do
+          example_group = Class.new(ExampleGroup) do
+            describe('example')
+            FOO = 1
+            it "should reference FOO" do
+              FOO.should == 1
+            end
+          end
+          example_group.run
+          Object.const_defined?(:FOO).should == false
+        end
+      end
+
+      describe '#register' do
+        it "should add ExampleGroup to set of ExampleGroups to be run" do
+          options.example_groups.delete(example_group)
+          options.example_groups.should_not include(example_group)
+          
+          example_group.register {}
+          options.example_groups.should include(example_group)
+        end
+      end
+
+      describe '#unregister' do
+        before do
+          options.example_groups.should include(example_group)
+        end
+
+        it "should remove ExampleGroup from set of ExampleGroups to be run" do
+          example_group.unregister
+          options.example_groups.should_not include(example_group)
+        end
+      end
+
+      describe "#registration_backtrace" do
+        it "returns the backtrace of where the ExampleGroup was registered" do
+          example_group = Class.new(ExampleGroup)
+          example_group.registration_backtrace.join("\n").should include("#{__FILE__}:#{__LINE__-1}")
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/example/example_group_spec.rb b/vendor/gems/rspec/spec/spec/example/example_group_spec.rb
new file mode 100644
index 0000000..93e558a
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_group_spec.rb
@@ -0,0 +1,711 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    class ExampleModuleScopingSpec < ExampleGroup
+      describe ExampleGroup, "via a class definition"
+
+      module Foo
+        module Bar
+          def self.loaded?
+            true
+          end
+        end
+      end
+      include Foo
+
+      it "should understand module scoping" do
+        Bar.should be_loaded
+      end
+
+      @@foo = 1
+
+      it "should allow class variables to be defined" do
+        @@foo.should == 1
+      end
+    end
+
+    class ExampleClassVariablePollutionSpec < ExampleGroup
+      describe ExampleGroup, "via a class definition without a class variable"
+
+      it "should not retain class variables from other Example classes" do
+        proc do
+          @@foo
+        end.should raise_error
+      end
+    end
+
+    describe ExampleGroup, "#pending" do
+      it "should 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::Example::ExamplePendingError, "something")
+        block_ran.should == true
+      end
+
+      it "should raise Spec::Example::PendingExampleFixedError when its block does not fail" do
+        block_ran = false
+        lambda {
+          pending("something") do
+            block_ran = true
+          end
+        }.should raise_error(Spec::Example::PendingExampleFixedError, "Expected pending 'something' to fail. No Error was raised.")
+        block_ran.should == true
+      end
+    end
+
+    describe ExampleGroup, "#run with failure in example", :shared => true do
+      it "should add an example failure to the TestResult" do
+        example_group.run.should be_false
+      end
+    end
+
+    describe ExampleGroup, "#run" do
+      it_should_behave_like "sandboxed rspec_options"
+      attr_reader :example_group, :formatter, :reporter
+      before :each do
+        @formatter = mock("formatter", :null_object => true)
+        options.formatters << formatter
+        options.backtrace_tweaker = mock("backtrace_tweaker", :null_object => true)
+        @reporter = FakeReporter.new(options)
+        options.reporter = reporter
+        @example_group = Class.new(ExampleGroup) do
+          describe("example")
+          it "does nothing" do
+          end
+        end
+        class << example_group
+          public :include
+        end
+      end
+
+      after :each do
+        ExampleGroup.reset
+      end
+
+      it "should not run when there are no examples" do
+        example_group = Class.new(ExampleGroup) do
+          describe("Foobar")
+        end
+        example_group.examples.should be_empty
+
+        reporter = mock("Reporter")
+        reporter.should_not_receive(:add_example_group)
+        example_group.run
+      end
+      
+      describe "when before_each fails" do
+        before(:each) do
+          $example_ran = $after_each_ran = false
+          @example_group = describe("Foobar") do
+            before(:each) {raise}
+            it "should not be run" do
+              $example_ran = true
+            end
+            after(:each) do
+              $after_each_ran = true
+            end
+          end
+        end
+
+        it "should not run example block" do
+          example_group.run
+          $example_ran.should be_false
+        end
+        
+        it "should run after_each" do
+          example_group.run
+          $after_each_ran.should be_true
+        end
+
+        it "should report failure location when in before_each" do
+          reporter.should_receive(:example_finished) do |example_group, error|
+            error.message.should eql("in before_each")
+          end
+          example_group.run
+        end
+      end
+
+      describe ExampleGroup, "#run on dry run" do
+        before do
+          @options.dry_run = true
+        end
+
+        it "should not run before(:all) or after(:all)" do
+          before_all_ran = false
+          after_all_ran = false
+          ExampleGroup.before(:all) { before_all_ran = true }
+          ExampleGroup.after(:all) { after_all_ran = true }
+          example_group.it("should") {}
+          example_group.run
+          before_all_ran.should be_false
+          after_all_ran.should be_false
+        end
+
+        it "should not run example" do
+          example_ran = false
+          example_group.it("should") {example_ran = true}
+          example_group.run
+          example_ran.should be_false
+        end
+      end
+
+      describe ExampleGroup, "#run with specified examples" do
+        attr_reader :examples_that_were_run
+        before do
+          @examples_that_were_run = []
+        end
+
+        describe "when specified_examples matches entire ExampleGroup" do
+          before do
+            examples_that_were_run = @examples_that_were_run
+            @example_group = Class.new(ExampleGroup) do
+              describe("the ExampleGroup")
+              it("should be run") do
+                examples_that_were_run << 'should be run'
+              end
+
+              it("should also be run") do
+                examples_that_were_run << 'should also be run'
+              end
+            end
+            options.examples = ["the ExampleGroup"]
+          end
+
+          it "should not run the Examples in the ExampleGroup" do
+            example_group.run
+            examples_that_were_run.should == ['should be run', 'should also be run']
+          end
+        end
+
+        describe ExampleGroup, "#run when specified_examples matches only Example description" do
+          before do
+            examples_that_were_run = @examples_that_were_run
+            @example_group = Class.new(ExampleGroup) do
+              describe("example")
+              it("should be run") do
+                examples_that_were_run << 'should be run'
+              end
+            end
+            options.examples = ["should be run"]
+          end
+
+          it "should not run the example" do
+            example_group.run
+            examples_that_were_run.should == ['should be run']
+          end
+        end
+
+        describe ExampleGroup, "#run when specified_examples does not match an Example description" do
+          before do
+            examples_that_were_run = @examples_that_were_run
+            @example_group = Class.new(ExampleGroup) do
+              describe("example")
+              it("should be something else") do
+                examples_that_were_run << 'should be something else'
+              end
+            end
+            options.examples = ["does not match anything"]
+          end
+
+          it "should not run the example" do
+            example_group.run
+            examples_that_were_run.should == []
+          end
+        end
+
+        describe ExampleGroup, "#run when specified_examples matches an Example description" do
+          before do
+            examples_that_were_run = @examples_that_were_run
+            @example_group = Class.new(ExampleGroup) do
+              describe("example")
+              it("should be run") do
+                examples_that_were_run << 'should be run'
+              end
+              it("should not be run") do
+                examples_that_were_run << 'should not be run'
+              end
+            end
+            options.examples = ["should be run"]
+          end
+
+          it "should run only the example, when there in only one" do
+            example_group.run
+            examples_that_were_run.should == ["should be run"]
+          end
+
+          it "should run only the one example" do
+            example_group.run
+            examples_that_were_run.should == ["should be run"]          end
+        end
+      end
+
+      describe ExampleGroup, "#run with success" do
+        before do
+          @special_example_group = Class.new(ExampleGroup)
+          ExampleGroupFactory.register(:special, @special_example_group)
+          @not_special_example_group = Class.new(ExampleGroup)
+          ExampleGroupFactory.register(:not_special, @not_special_example_group)
+        end
+
+        after do
+          ExampleGroupFactory.reset
+        end
+
+        it "should send reporter add_example_group" do
+          example_group.run
+          reporter.example_groups.should == [example_group]
+        end
+
+        it "should run example on run" do
+          example_ran = false
+          example_group.it("should") {example_ran = true}
+          example_group.run
+          example_ran.should be_true
+        end
+
+        it "should run before(:all) block only once" do
+          before_all_run_count_run_count = 0
+          example_group.before(:all) {before_all_run_count_run_count += 1}
+          example_group.it("test") {true}
+          example_group.it("test2") {true}
+          example_group.run
+          before_all_run_count_run_count.should == 1
+        end
+
+        it "should run after(:all) block only once" do
+          after_all_run_count = 0
+          example_group.after(:all) {after_all_run_count += 1}
+          example_group.it("test") {true}
+          example_group.it("test2") {true}
+          example_group.run
+          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 = ""
+          example_group.before(:all) { @instance_var = context_instance_value_in }
+          example_group.after(:all) { context_instance_value_out = @instance_var }
+          example_group.it("test") {true}
+          example_group.run
+          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 = ""
+          example_group.before(:all) { @instance_var = context_instance_value_in }
+          example_group.it("test") {context_instance_value_out = @instance_var}
+          example_group.run
+          context_instance_value_in.should == context_instance_value_out
+        end
+
+        it "should not add global before callbacks for untargetted example_group" do
+          fiddle = []
+
+          ExampleGroup.before(:all) { fiddle << "Example.before(:all)" }
+          ExampleGroup.prepend_before(:all) { fiddle << "Example.prepend_before(:all)" }
+          @special_example_group.before(:each) { fiddle << "Example.before(:each, :type => :special)" }
+          @special_example_group.prepend_before(:each) { fiddle << "Example.prepend_before(:each, :type => :special)" }
+          @special_example_group.before(:all) { fiddle << "Example.before(:all, :type => :special)" }
+          @special_example_group.prepend_before(:all) { fiddle << "Example.prepend_before(:all, :type => :special)" }
+
+          example_group = Class.new(ExampleGroup) do
+            describe("I'm not special", :type => :not_special)
+            it "does nothing"
+          end
+          example_group.run
+          fiddle.should == [
+            'Example.prepend_before(:all)',
+            'Example.before(:all)',
+          ]
+        end
+
+        it "should add global before callbacks for targetted example_groups" do
+          fiddle = []
+
+          ExampleGroup.before(:all) { fiddle << "Example.before(:all)" }
+          ExampleGroup.prepend_before(:all) { fiddle << "Example.prepend_before(:all)" }
+          @special_example_group.before(:each) { fiddle << "special.before(:each, :type => :special)" }
+          @special_example_group.prepend_before(:each) { fiddle << "special.prepend_before(:each, :type => :special)" }
+          @special_example_group.before(:all) { fiddle << "special.before(:all, :type => :special)" }
+          @special_example_group.prepend_before(:all) { fiddle << "special.prepend_before(:all, :type => :special)" }
+          @special_example_group.append_before(:each) { fiddle << "special.append_before(:each, :type => :special)" }
+
+          example_group = Class.new(@special_example_group).describe("I'm a special example_group") {}
+          example_group.it("test") {true}
+          example_group.run
+          fiddle.should == [
+            'Example.prepend_before(:all)',
+            'Example.before(:all)',
+            'special.prepend_before(:all, :type => :special)',
+            'special.before(:all, :type => :special)',
+            'special.prepend_before(:each, :type => :special)',
+            'special.before(:each, :type => :special)',
+            'special.append_before(:each, :type => :special)',
+          ]
+        end
+
+        it "should order before callbacks from global to local" do
+          fiddle = []
+          ExampleGroup.prepend_before(:all) { fiddle << "Example.prepend_before(:all)" }
+          ExampleGroup.before(:all) { fiddle << "Example.before(:all)" }
+          example_group.prepend_before(:all) { fiddle << "prepend_before(:all)" }
+          example_group.before(:all) { fiddle << "before(:all)" }
+          example_group.prepend_before(:each) { fiddle << "prepend_before(:each)" }
+          example_group.before(:each) { fiddle << "before(:each)" }
+          example_group.run
+          fiddle.should == [
+            'Example.prepend_before(:all)',
+            'Example.before(:all)',
+            'prepend_before(:all)',
+            'before(:all)',
+            'prepend_before(:each)',
+            'before(:each)'
+          ]
+        end
+
+        it "should order after callbacks from local to global" do
+          fiddle = []
+          example_group.after(:each) { fiddle << "after(:each)" }
+          example_group.append_after(:each) { fiddle << "append_after(:each)" }
+          example_group.after(:all) { fiddle << "after(:all)" }
+          example_group.append_after(:all) { fiddle << "append_after(:all)" }
+          ExampleGroup.after(:all) { fiddle << "Example.after(:all)" }
+          ExampleGroup.append_after(:all) { fiddle << "Example.append_after(:all)" }
+          example_group.run
+          fiddle.should == [
+            'after(:each)',
+            'append_after(:each)',
+            'after(:all)',
+            'append_after(:all)',
+            'Example.after(:all)',
+            'Example.append_after(:all)'
+          ]
+        end
+
+        it "should have accessible instance methods from included module" do
+          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
+
+          example_group.include mod1, mod2
+
+          example_group.it("test") do
+            mod1_method
+            mod2_method
+          end
+          example_group.run
+          mod1_method_called.should be_true
+          mod2_method_called.should be_true
+        end
+
+        it "should include targetted modules included using configuration" do
+          mod1 = Module.new
+          mod2 = Module.new
+          mod3 = Module.new
+          Spec::Runner.configuration.include(mod1, mod2)
+          Spec::Runner.configuration.include(mod3, :type => :not_special)
+
+          example_group = Class.new(@special_example_group).describe("I'm special", :type => :special) do
+            it "does nothing"
+          end
+          example_group.run
+
+          example_group.included_modules.should include(mod1)
+          example_group.included_modules.should include(mod2)
+          example_group.included_modules.should_not include(mod3)
+        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?
+          example_group = Class.new(ExampleGroup) do
+            describe('example')
+            it "should respond to do_something" do
+              $included_predicate_matcher_found = respond_to?(:do_something)
+            end
+          end
+          example_group.run
+          $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
+
+            def teardown_mocks_for_rspec
+              $torn_down = true
+            end
+          end
+
+          begin
+            $included_module = nil
+            $torn_down = true
+            Spec::Runner.configuration.mock_with mod
+
+            example_group = Class.new(ExampleGroup) do
+              describe('example')
+              it "does nothing"
+            end
+            example_group.run
+
+            $included_module.should_not be_nil
+            $torn_down.should == true
+          ensure
+            Spec::Runner.configuration.mock_with :rspec
+          end
+        end
+      end
+
+      describe ExampleGroup, "#run with pending example that has a failing assertion" do
+        before do
+          example_group.it("should be pending") do
+            pending("Example fails") {false.should be_true}
+          end
+        end
+
+        it "should send example_pending to formatter" do
+          @formatter.should_receive(:example_pending).with("example", "should be pending", "Example fails")
+          example_group.run
+        end
+      end
+
+      describe ExampleGroup, "#run with pending example that does not have a failing assertion" do
+        it_should_behave_like "Spec::Example::ExampleGroup#run with failure in example"
+
+        before do
+          example_group.it("should be pending") do
+            pending("Example passes") {true.should be_true}
+          end
+        end
+
+        it "should send example_pending to formatter" do
+          @formatter.should_receive(:example_pending).with("example", "should be pending", "Example passes")
+          example_group.run
+        end
+      end
+
+      describe ExampleGroup, "#run when before(:all) fails" do
+        it_should_behave_like "Spec::Example::ExampleGroup#run with failure in example"
+
+        before do
+          ExampleGroup.before(:all) { raise NonStandardError, "before(:all) failure" }
+        end
+
+        it "should not run any example" do
+          spec_ran = false
+          example_group.it("test") {spec_ran = true}
+          example_group.run
+          spec_ran.should be_false
+        end
+
+        it "should run ExampleGroup after(:all)" do
+          after_all_ran = false
+          ExampleGroup.after(:all) { after_all_ran = true }
+          example_group.run
+          after_all_ran.should be_true
+        end
+
+        it "should run example_group after(:all)" do
+          after_all_ran = false
+          example_group.after(:all) { after_all_ran = true }
+          example_group.run
+          after_all_ran.should be_true
+        end
+
+        it "should supply before(:all) as description" do
+          @reporter.should_receive(:failure) do |example, error|
+            example.description.should eql("before(:all)")
+            error.message.should eql("before(:all) failure")
+          end
+
+          example_group.it("test") {true}
+          example_group.run
+        end
+      end
+
+      describe ExampleGroup, "#run when before(:each) fails" do
+        it_should_behave_like "Spec::Example::ExampleGroup#run with failure in example"
+
+        before do
+          ExampleGroup.before(:each) { raise NonStandardError }
+        end
+
+        it "should run after(:all)" do
+          after_all_ran = false
+          ExampleGroup.after(:all) { after_all_ran = true }
+          example_group.run
+          after_all_ran.should be_true
+        end
+      end
+
+      describe ExampleGroup, "#run when any example fails" do
+        it_should_behave_like "Spec::Example::ExampleGroup#run with failure in example"
+
+        before do
+          example_group.it("should") { raise NonStandardError }
+        end
+
+        it "should run after(:all)" do
+          after_all_ran = false
+          ExampleGroup.after(:all) { after_all_ran = true }
+          example_group.run
+          after_all_ran.should be_true
+        end
+      end
+
+      describe ExampleGroup, "#run when first after(:each) block fails" do
+        it_should_behave_like "Spec::Example::ExampleGroup#run with failure in example"
+
+        before do
+          class << example_group
+            attr_accessor :first_after_ran, :second_after_ran
+          end
+          example_group.first_after_ran = false
+          example_group.second_after_ran = false
+
+          example_group.after(:each) do
+            self.class.second_after_ran = true
+          end
+          example_group.after(:each) do
+            self.class.first_after_ran = true
+            raise "first"
+          end
+        end
+
+        it "should run second after(:each) block" do
+          reporter.should_receive(:example_finished) do |example, error|
+            example.should equal(example)
+            error.message.should eql("first")
+          end
+          example_group.run
+          example_group.first_after_ran.should be_true
+          example_group.second_after_ran.should be_true
+        end
+      end
+
+      describe ExampleGroup, "#run when first before(:each) block fails" do
+        it_should_behave_like "Spec::Example::ExampleGroup#run with failure in example"
+
+        before do
+          class << example_group
+            attr_accessor :first_before_ran, :second_before_ran
+          end
+          example_group.first_before_ran = false
+          example_group.second_before_ran = false
+
+          example_group.before(:each) do
+            self.class.first_before_ran = true
+            raise "first"
+          end
+          example_group.before(:each) do
+            self.class.second_before_ran = true
+          end
+        end
+
+        it "should not run second before(:each)" do
+          reporter.should_receive(:example_finished) do |name, error|
+            error.message.should eql("first")
+          end
+          example_group.run
+          example_group.first_before_ran.should be_true
+          example_group.second_before_ran.should be_false
+        end
+      end
+
+      describe ExampleGroup, "#run when failure in after(:all)" do
+        it_should_behave_like "Spec::Example::ExampleGroup#run with failure in example"
+
+        before do
+          ExampleGroup.after(:all) { raise NonStandardError, "in after(:all)" }
+        end
+
+        it "should return false" do
+          example_group.run.should be_false
+        end
+      end
+    end
+
+    class ExampleSubclass < ExampleGroup
+    end
+
+    describe ExampleGroup, "subclasses" do
+      after do
+        ExampleGroupFactory.reset
+      end
+
+      it "should have access to the described_type" do
+        example_group = Class.new(ExampleSubclass) do
+          describe(Array)
+        end
+        example_group.send(:described_type).should == Array
+      end
+
+      it "should concat descriptions when nested" do
+        example_group = Class.new(ExampleSubclass) do
+          describe(Array)
+          $nested_group = describe("when empty") do
+          end
+        end
+        $nested_group.description.to_s.should == "Array when empty"
+      end
+    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 "An", Enumerable, "as a second argument" 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 Enumerable do
+      describe "as the parent of nested example groups" do
+        it "should be included in examples because it is a module" do
+          pending("need to make sure nested groups know the described type") do
+            map{|e| e.to_i}.should == [4,2,1]
+          end
+        end
+      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/example/example_matcher_spec.rb b/vendor/gems/rspec/spec/spec/example/example_matcher_spec.rb
new file mode 100644
index 0000000..ea0dfe0
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_matcher_spec.rb
@@ -0,0 +1,96 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Example
+    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, "#matches?" do
+      include ExampleMatcherSpecHelper
+      
+      it "should match correct example_group and example" do
+        matcher = ExampleMatcher.new("example_group", "example")
+        matcher.should match_description("example_group example")
+      end
+      
+      it "should not match wrong example" do
+        matcher = ExampleMatcher.new("example_group", "other example")
+        matcher.should_not match_description("example_group example")
+      end
+      
+      it "should not match wrong example_group" do
+        matcher = ExampleMatcher.new("other example_group", "example")
+        matcher.should_not match_description("example_group example")
+      end
+      
+      it "should match example only" do
+        matcher = ExampleMatcher.new("example_group", "example")
+        matcher.should match_description("example")
+      end
+
+      it "should match example_group only" do
+        matcher = ExampleMatcher.new("example_group", "example")
+        matcher.should match_description("example_group")
+      end
+
+      it "should match example_group ending with before(:all)" do
+        matcher = ExampleMatcher.new("example_group", "example")
+        matcher.should match_description("example_group before(:all)")
+      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 example_group is modularized" do
+        matcher = ExampleMatcher.new("MyModule::MyClass", "example")
+        matcher.should match_description("MyClass example")
+      end      
+    end
+
+    describe ExampleMatcher, "#matches? 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, "#matches? 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/example/example_methods_spec.rb b/vendor/gems/rspec/spec/spec/example/example_methods_spec.rb
new file mode 100644
index 0000000..c185228
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_methods_spec.rb
@@ -0,0 +1,104 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    module ModuleThatIsReopened
+    end
+
+    module ExampleMethods
+      include ModuleThatIsReopened
+    end
+
+    module ModuleThatIsReopened
+      def module_that_is_reopened_method
+      end
+    end
+
+    describe ExampleMethods do
+      describe "with an included module that is reopened" do
+        it "should have repoened methods" do
+          method(:module_that_is_reopened_method).should_not be_nil
+        end
+      end
+
+      describe "lifecycle" do
+        before do
+          @options = ::Spec::Runner::Options.new(StringIO.new, StringIO.new)
+          @options.formatters << mock("formatter", :null_object => true)
+          @options.backtrace_tweaker = mock("backtrace_tweaker", :null_object => true)
+          @reporter = FakeReporter.new(@options)
+          @options.reporter = @reporter
+
+          ExampleMethods.before_all_parts.should == []
+          ExampleMethods.before_each_parts.should == []
+          ExampleMethods.after_each_parts.should == []
+          ExampleMethods.after_all_parts.should == []
+          def ExampleMethods.count
+            @count ||= 0
+            @count = @count + 1
+            @count
+          end
+        end
+
+        after do
+          ExampleMethods.instance_variable_set("@before_all_parts", [])
+          ExampleMethods.instance_variable_set("@before_each_parts", [])
+          ExampleMethods.instance_variable_set("@after_each_parts", [])
+          ExampleMethods.instance_variable_set("@after_all_parts", [])
+        end
+
+        it "should pass before and after callbacks to all ExampleGroup subclasses" do
+          ExampleMethods.before(:all) do
+            ExampleMethods.count.should == 1
+          end
+
+          ExampleMethods.before(:each) do
+            ExampleMethods.count.should == 2
+          end
+
+          ExampleMethods.after(:each) do
+            ExampleMethods.count.should == 3
+          end
+
+          ExampleMethods.after(:all) do
+            ExampleMethods.count.should == 4
+          end
+
+          @example_group = Class.new(ExampleGroup) do
+            it "should use ExampleMethods callbacks" do
+            end
+          end
+          @example_group.run
+          ExampleMethods.count.should == 5
+        end
+
+        describe "run_with_description_capturing" do
+          before(:each) do
+            @example_group = Class.new(ExampleGroup) do end
+            @example = @example_group.new("foo", &(lambda { 2.should == 2 }))
+            @example.run_with_description_capturing
+          end
+
+          it "should provide the generated description" do
+            @example.instance_eval { @_matcher_description }.should == "should == 2"
+          end
+
+          it "should clear the global generated_description" do
+            Spec::Matchers.generated_description.should == nil
+          end
+        end
+      end
+
+      describe "#implementation_backtrace" do
+        it "returns the backtrace of where the implementation was defined" do
+          example_group = Class.new(ExampleGroup) do
+            it "should use ExampleMethods callbacks" do
+            end
+          end
+          example = example_group.examples.first
+          example.implementation_backtrace.join("\n").should include("#{__FILE__}:#{__LINE__-4}")
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/example/example_runner_spec.rb b/vendor/gems/rspec/spec/spec/example/example_runner_spec.rb
new file mode 100644
index 0000000..1b5abdf
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_runner_spec.rb
@@ -0,0 +1,194 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Example
+    # describe "Spec::Example::ExampleRunner", "#run", :shared => true do
+    #   before(:each) do
+    #     @options = ::Spec::Runner::Options.new(StringIO.new, StringIO.new)
+    #     @reporter = ::Spec::Runner::Reporter.new(@options)
+    #     @options.reporter = @reporter
+    #     @example_group_class = Class.new(ExampleGroup) do
+    #       plugin_mock_framework
+    #       describe("Some Examples")
+    #     end
+    #   end
+    # 
+    #   def create_runner(example_definition)
+    #     example = @example_group_class.new(example_definition)
+    #     runner = ExampleGroup.new(@options, example)
+    #     runner.stub!(:verify_mocks)
+    #     runner.stub!(:teardown_mocks)
+    #     runner
+    #   end
+    # end
+    # 
+    # describe ExampleRunner, "#run with blank passing example" do
+    #   it_should_behave_like "Spec::Example::ExampleRunner#run"
+    # 
+    #   before do
+    #     @e = @example_group_class.it("example") {}
+    #     @runner = create_runner(@e)
+    #   end
+    #   
+    #   it "should send reporter example_started" do
+    #     @reporter.should_receive(:example_started).with(equal(@e))
+    #     @runner.run
+    #   end
+    # 
+    #   it "should report its name for dry run" do
+    #     @options.dry_run = true
+    #     @reporter.should_receive(:example_finished).with(equal(@e), nil)
+    #     @runner.run
+    #   end
+    # 
+    #   it "should report success" do
+    #     @reporter.should_receive(:example_finished).with(equal(@e), nil)
+    #     @runner.run
+    #   end
+    # end
+    # 
+    # describe ExampleRunner, "#run with a failing example" do
+    #   predicate_matchers[:is_a] = [:is_a?]
+    #   it_should_behave_like "Spec::Example::ExampleRunner#run"
+    # 
+    #   before do
+    #     @e = @example_group_class.it("example") do
+    #       (2+2).should == 5
+    #     end
+    #     @runner = create_runner(@e)
+    #   end
+    # 
+    #   it "should report failure due to failure" do
+    #     @reporter.should_receive(:example_finished).with(
+    #       equal(@e),
+    #       is_a(Spec::Expectations::ExpectationNotMetError)
+    #     )
+    #     @runner.run
+    #   end
+    # end
+    # 
+    # describe ExampleRunner, "#run with a erroring example" do
+    #   it_should_behave_like "Spec::Example::ExampleRunner#run"
+    # 
+    #   before do
+    #     @error = error = NonStandardError.new("in body")
+    #     @example_definition = @example_group_class.it("example") do
+    #       raise(error)
+    #     end
+    #     @runner = create_runner(@example_definition)
+    #   end
+    # 
+    #   it "should report failure due to error" do
+    #     @reporter.should_receive(:example_finished).with(
+    #       equal(@example_definition),
+    #       @error
+    #     )
+    #     @runner.run
+    #   end
+    # 
+    #   it "should run after_each block" do
+    #     @example_group_class.after(:each) do
+    #       raise("in after_each")
+    #     end
+    #     @reporter.should_receive(:example_finished) do |example_definition, error|
+    #       example_definition.should equal(@example_definition)
+    #       error.message.should eql("in body")
+    #     end
+    #     @runner.run
+    #   end      
+    # end
+    # 
+    # describe ExampleRunner, "#run where after_each fails" do
+    #   it_should_behave_like "Spec::Example::ExampleRunner#run"
+    # 
+    #   before do
+    #     @example_ran = example_ran = false
+    #     @example_definition = @example_group_class.it("should not run") do
+    #       example_ran = true
+    #     end
+    #     @runner = create_runner(@example_definition)
+    #     @example_group_class.after(:each) { raise(NonStandardError.new("in after_each")) }
+    #   end
+    # 
+    #   it "should report failure location when in after_each" do
+    #     @reporter.should_receive(:example_finished) do |example_definition, error|
+    #       example_definition.should equal(@example_definition)
+    #       error.message.should eql("in after_each")
+    #     end
+    #     @runner.run
+    #   end
+    # end
+    # 
+    # describe ExampleRunner, "#run with use cases" do
+    #   predicate_matchers[:is_a] = [:is_a?]
+    #   it_should_behave_like "Spec::Example::ExampleRunner#run"
+    # 
+    #   it "should report NO NAME when told to use generated description with --dry-run" do
+    #     @options.dry_run = true
+    #     example_definition = @example_group_class.it() do
+    #       5.should == 5
+    #     end
+    #     runner = create_runner(example_definition)
+    # 
+    #     @reporter.should_receive(:example_finished) do |example_definition, error|
+    #       example_definition.description.should == "NO NAME (Because of --dry-run)"
+    #      end
+    #     runner.run
+    #   end
+    # 
+    #   it "should report given name if present with --dry-run" do
+    #     @options.dry_run = true
+    #     example_definition = @example_group_class.it("example name") do
+    #       5.should == 5
+    #     end
+    #     runner = create_runner(example_definition)
+    # 
+    #     @reporter.should_receive(:example_finished) do |example_definition, error|
+    #       example_definition.description.should == "example name"
+    #      end
+    #     runner.run
+    #   end
+    # 
+    #   it "should report NO NAME when told to use generated description with no expectations" do
+    #     example_definition = @example_group_class.it() {}
+    #     runner = create_runner(example_definition)
+    #     @reporter.should_receive(:example_finished) do |example, error|
+    #       example.description.should == "NO NAME (Because there were no expectations)"
+    #     end
+    #     runner.run
+    #   end
+    # 
+    #   it "should report NO NAME when told to use generated description and matcher fails" do
+    #     example_definition = @example_group_class.it() do
+    #       5.should "" # Has no matches? method..
+    #     end
+    #     runner = create_runner(example_definition)
+    # 
+    #     @reporter.should_receive(:example_finished) do |example, error|
+    #       example_definition.description.should == "NO NAME (Because of Error raised in matcher)"
+    #     end
+    #     runner.run
+    #   end
+    # 
+    #   it "should report generated description when told to and it is available" do
+    #     example_definition = @example_group_class.it() {
+    #       5.should == 5
+    #     }
+    #     runner = create_runner(example_definition)
+    #     
+    #     @reporter.should_receive(:example_finished) do |example_definition, error|
+    #       example_definition.description.should == "should == 5"
+    #     end
+    #     runner.run
+    #   end
+    # 
+    #   it "should unregister description_generated callback (lest a memory leak should build up)" do
+    #     example_definition = @example_group_class.it("something")
+    #     runner = create_runner(example_definition)
+    # 
+    #     Spec::Matchers.should_receive(:example_finished)
+    #     runner.run
+    #   end
+    # end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/example/example_spec.rb b/vendor/gems/rspec/spec/spec/example/example_spec.rb
new file mode 100644
index 0000000..c8125b4
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/example_spec.rb
@@ -0,0 +1,53 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    # describe Example do
+    #   before(:each) do
+    #     @example = Example.new "example" do
+    #       foo
+    #     end
+    #   end
+    #   
+    #   it "should tell you its docstring" do
+    #     @example.description.should == "example"
+    #   end
+    # 
+    #   it "should execute its block in the context provided" do
+    #     context = Class.new do
+    #       def foo
+    #         "foo"
+    #       end
+    #     end.new
+    #     @example.run_in(context).should == "foo"
+    #   end
+    # end
+    # 
+    # describe Example, "#description" do
+    #   it "should default to NO NAME when not passed anything when there are no matchers" do
+    #     example = Example.new {}
+    #     example.run_in(Object.new)
+    #     example.description.should == "NO NAME"
+    #   end
+    # 
+    #   it "should default to NO NAME description (Because of --dry-run) when passed nil and there are no matchers" do
+    #     example = Example.new(nil) {}
+    #     example.run_in(Object.new)
+    #     example.description.should == "NO NAME"
+    #   end
+    # 
+    #   it "should allow description to be overridden" do
+    #     example = Example.new("Test description")
+    #     example.description.should == "Test description"
+    #   end
+    # 
+    #   it "should use description generated from matcher when there is no passed in description" do
+    #     example = Example.new(nil) do
+    #       1.should == 1
+    #     end
+    #     example.run_in(Object.new)
+    #     example.description.should == "should == 1"
+    #   end
+    # end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/example/nested_example_group_spec.rb b/vendor/gems/rspec/spec/spec/example/nested_example_group_spec.rb
new file mode 100644
index 0000000..35e8a98
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/nested_example_group_spec.rb
@@ -0,0 +1,59 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    describe 'Nested Example Groups' do
+      parent = self
+      
+      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
+
+      describe 'nested example group' do
+        self.superclass.should == parent
+        
+        it "should run all before and after callbacks" do
+          count.should == 5
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/example/pending_module_spec.rb b/vendor/gems/rspec/spec/spec/example/pending_module_spec.rb
new file mode 100644
index 0000000..c3ab012
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/pending_module_spec.rb
@@ -0,0 +1,31 @@
+module Spec
+  module Example
+    describe Pending do
+      
+      it 'should raise an ExamplePendingError if no block is supplied' do
+        lambda {
+          include Pending
+          pending "TODO"
+        }.should raise_error(ExamplePendingError, /TODO/)
+      end
+      
+      it 'should raise an ExamplePendingError if a supplied block fails as expected' do
+        lambda {
+          include Pending
+          pending "TODO" do
+            raise "oops"
+          end
+        }.should raise_error(ExamplePendingError, /TODO/)
+      end
+      
+      it 'should raise a PendingExampleFixedError if a supplied block starts working' do
+        lambda {
+          include Pending
+          pending "TODO" do
+            # success!
+          end
+        }.should raise_error(PendingExampleFixedError, /TODO/)
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/example/predicate_matcher_spec.rb b/vendor/gems/rspec/spec/spec/example/predicate_matcher_spec.rb
new file mode 100755
index 0000000..7c4638b
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/predicate_matcher_spec.rb
@@ -0,0 +1,21 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    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/example/shared_example_group_spec.rb b/vendor/gems/rspec/spec/spec/example/shared_example_group_spec.rb
new file mode 100644
index 0000000..803536a
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/shared_example_group_spec.rb
@@ -0,0 +1,265 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    describe ExampleGroup, "with :shared => true" do
+      it_should_behave_like "sandboxed rspec_options"
+      attr_reader :formatter, :example_group
+      before(:each) do
+        @formatter = Spec::Mocks::Mock.new("formatter", :null_object => true)
+        options.formatters << formatter
+        @example_group = Class.new(ExampleGroup).describe("example_group")
+        class << example_group
+          public :include
+        end
+      end
+
+      after(:each) do
+        @formatter.rspec_verify
+        @example_group = nil
+        $shared_example_groups.clear unless $shared_example_groups.nil?
+      end
+
+      def make_shared_example_group(name, opts=nil, &block)
+        example_group = SharedExampleGroup.new(name, :shared => true, &block)
+        SharedExampleGroup.add_shared_example_group(example_group)
+        example_group
+      end
+
+      def non_shared_example_group()
+        @non_shared_example_group ||= Class.new(ExampleGroup).describe("example_group")
+      end
+
+      it "should accept an optional options hash" do
+        lambda { Class.new(ExampleGroup).describe("context") }.should_not raise_error(Exception)
+        lambda { Class.new(ExampleGroup).describe("context", :shared => true) }.should_not raise_error(Exception)
+      end
+
+      it "should return all shared example_groups" do
+        b1 = make_shared_example_group("b1", :shared => true) {}
+        b2 = make_shared_example_group("b2", :shared => true) {}
+
+        b1.should_not be(nil)
+        b2.should_not be(nil)
+
+        SharedExampleGroup.find_shared_example_group("b1").should equal(b1)
+        SharedExampleGroup.find_shared_example_group("b2").should equal(b2)
+      end
+
+      it "should register as shared example_group" do
+        example_group = make_shared_example_group("example_group") {}
+        SharedExampleGroup.shared_example_groups.should include(example_group)
+      end
+
+      it "should not be shared when not configured as shared" do
+        example_group = non_shared_example_group
+        SharedExampleGroup.shared_example_groups.should_not include(example_group)
+      end
+
+      it "should complain when adding a second shared example_group with the same description" do
+        describe "shared example_group", :shared => true do
+        end
+        lambda do
+          describe "shared example_group", :shared => true do
+          end
+        end.should raise_error(ArgumentError)
+      end
+
+      it "should NOT complain when adding the same shared example_group instance again" do
+        shared_example_group = Class.new(ExampleGroup).describe("shared example_group", :shared => true)
+        SharedExampleGroup.add_shared_example_group(shared_example_group)
+        SharedExampleGroup.add_shared_example_group(shared_example_group)
+      end
+
+      it "should NOT complain when adding the same shared example_group again (i.e. file gets reloaded)" do
+        lambda do
+          2.times do
+            describe "shared example_group 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 example_group in same file with different absolute path" do
+        shared_example_group_1 = Class.new(ExampleGroup).describe(
+          "shared example_group",
+          :shared => true,
+          :spec_path => "/my/spec/a/../shared.rb"
+        )
+        shared_example_group_2 = Class.new(ExampleGroup).describe(
+          "shared example_group",
+          :shared => true,
+          :spec_path => "/my/spec/b/../shared.rb"
+        )
+
+        SharedExampleGroup.add_shared_example_group(shared_example_group_1)
+        SharedExampleGroup.add_shared_example_group(shared_example_group_2)
+      end
+
+      it "should complain when adding a different shared example_group with the same name in a different file with the same basename" do
+        shared_example_group_1 = Class.new(ExampleGroup).describe(
+          "shared example_group",
+          :shared => true,
+          :spec_path => "/my/spec/a/shared.rb"
+        )
+        shared_example_group_2 = Class.new(ExampleGroup).describe(
+          "shared example_group",
+          :shared => true,
+          :spec_path => "/my/spec/b/shared.rb"
+        )
+
+        SharedExampleGroup.add_shared_example_group(shared_example_group_1)
+        lambda do
+          SharedExampleGroup.add_shared_example_group(shared_example_group_2)
+        end.should raise_error(ArgumentError, /already exists/)
+      end
+
+      it "should add examples to current example_group using it_should_behave_like" do
+        shared_example_group = make_shared_example_group("shared example_group") do
+          it("shared example") {}
+          it("shared example 2") {}
+        end
+
+        example_group.it("example") {}
+        example_group.number_of_examples.should == 1
+        example_group.it_should_behave_like("shared example_group")
+        example_group.number_of_examples.should == 3
+      end
+
+      it "should add examples to current example_group using include" do
+        shared_example_group = describe "all things", :shared => true do
+          it "should do stuff" do end
+        end
+        
+        example_group = describe "one thing" do
+          include shared_example_group
+        end
+        
+        example_group.number_of_examples.should == 1
+      end
+
+      it "should add examples to current example_group using it_should_behave_like with a module" do
+        AllThings = describe "all things", :shared => true do
+          it "should do stuff" do end
+        end
+        
+        example_group = describe "one thing" do
+          it_should_behave_like AllThings
+        end
+        
+        example_group.number_of_examples.should == 1
+      end
+
+      it "should run shared examples" do
+        shared_example_ran = false
+        shared_example_group = make_shared_example_group("shared example_group") do
+          it("shared example") { shared_example_ran = true }
+        end
+
+        example_ran = false
+
+        example_group.it_should_behave_like("shared example_group")
+        example_group.it("example") {example_ran = true}
+        example_group.run
+        example_ran.should be_true
+        shared_example_ran.should be_true
+      end
+
+      it "should run setup and teardown from shared example_group" do
+        shared_setup_ran = false
+        shared_teardown_ran = false
+        shared_example_group = make_shared_example_group("shared example_group") do
+          before { shared_setup_ran = true }
+          after { shared_teardown_ran = true }
+          it("shared example") { shared_example_ran = true }
+        end
+
+        example_ran = false
+
+        example_group.it_should_behave_like("shared example_group")
+        example_group.it("example") {example_ran = true}
+        example_group.run
+        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 example_group" do
+        shared_before_all_run_count = 0
+        shared_after_all_run_count = 0
+        shared_example_group = make_shared_example_group("shared example_group") do
+          before(:all) { shared_before_all_run_count += 1}
+          after(:all) { shared_after_all_run_count += 1}
+          it("shared example") { shared_example_ran = true }
+        end
+
+        example_ran = false
+
+        example_group.it_should_behave_like("shared example_group")
+        example_group.it("example") {example_ran = true}
+        example_group.run
+        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 example_group, into current example_group" do
+        @formatter.should_receive(:add_example_group).with(any_args)
+
+        shared_example_group = make_shared_example_group("shared example_group") do
+          it("shared example") { shared_example_ran = true }
+        end
+
+        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_example_group.include mod2
+
+        example_group.it_should_behave_like("shared example_group")
+        example_group.include mod1
+
+        example_group.it("test") do
+          mod1_method
+          mod2_method
+        end
+        example_group.run
+        mod1_method_called.should be_true
+        mod2_method_called.should be_true
+      end
+
+      it "should make methods defined in the shared example_group available in consuming example_group" do
+        shared_example_group = make_shared_example_group("shared example_group xyz") do
+          def a_shared_helper_method
+            "this got defined in a shared example_group"
+          end
+        end
+        example_group.it_should_behave_like("shared example_group xyz")
+        success = false
+        example_group.it("should access a_shared_helper_method") do
+          a_shared_helper_method
+          success = true
+        end
+        example_group.run
+        success.should be_true
+      end
+
+      it "should raise when named shared example_group can not be found" do
+        lambda {
+          example_group.it_should_behave_like("non-existent shared example group")
+          violated
+        }.should raise_error("Shared Example Group 'non-existent shared example group' can not be found")
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/example/subclassing_example_group_spec.rb b/vendor/gems/rspec/spec/spec/example/subclassing_example_group_spec.rb
new file mode 100644
index 0000000..888f2ce
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/example/subclassing_example_group_spec.rb
@@ -0,0 +1,25 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Example
+    class GrandParentExampleGroup < Spec::Example::ExampleGroup
+      describe "Grandparent ExampleGroup"
+    end
+
+    class ParentExampleGroup < GrandParentExampleGroup
+      describe "Parent ExampleGroup"
+      it "should bar" do
+      end
+    end
+
+    class ChildExampleGroup < ParentExampleGroup
+      describe "Child ExampleGroup"
+      it "should bam" do
+      end
+    end
+
+    describe ChildExampleGroup do
+
+    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 0000000..ea72084
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/expectations/differs/default_spec.rb
@@ -0,0 +1,109 @@
+require File.dirname(__FILE__) + '/../../../spec_helper.rb'
+
+module Spec
+  module Fixtures
+    class Animal
+      def initialize(name,species)
+        @name, at species = name,species
+      end
+
+      def inspect
+        <<-EOA
+<Animal
+  name=#{@name},
+  species=#{@species}
+>
+        EOA
+      end
+    end
+  end
+end
+
+describe "Diff" do
+  before(:each) do
+    @options = ::Spec::Runner::Options.new(StringIO.new, StringIO.new)
+    @differ = Spec::Expectations::Differs::Default.new(@options)
+  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
+    @options = Spec::Runner::Options.new(StringIO.new, StringIO.new)
+    @options.diff_format = :context
+    @differ = Spec::Expectations::Differs::Default.new(@options)
+  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 0000000..0d9335b
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/expectations/extensions/object_spec.rb
@@ -0,0 +1,107 @@
+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
+  
+  it "should raise error if it receives false directly" do
+    lambda {
+      @target.should false
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+  
+  it "should raise error if it receives false (evaluated)" do
+    lambda {
+      @target.should eql?("foo")
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+  
+  it "should raise error if it receives true" do
+    lambda {
+      @target.should true
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+  
+  it "should raise error if it receives nil" do
+    lambda {
+      @target.should nil
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+
+  it "should raise error if it receives no argument and it is not used as a left side of an operator" do
+    pending "Is it even possible to catch this?"
+    lambda {
+      @target.should
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  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
+
+  it "should raise error if it receives false directly" do
+    lambda {
+      @target.should_not false
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+  
+  it "should raise error if it receives false (evaluated)" do
+    lambda {
+      @target.should_not eql?("foo")
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+  
+  it "should raise error if it receives true" do
+    lambda {
+      @target.should_not true
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+
+  it "should raise error if it receives nil" do
+    lambda {
+      @target.should_not nil
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  end
+
+  it "should raise error if it receives no argument and it is not used as a left side of an operator" do
+    pending "Is it even possible to catch this?"
+    lambda {
+      @target.should_not
+    }.should raise_error(Spec::Expectations::InvalidMatcherError)
+  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 0000000..4c369ce
--- /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/extensions/main_spec.rb b/vendor/gems/rspec/spec/spec/extensions/main_spec.rb
new file mode 100644
index 0000000..aabb616
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/extensions/main_spec.rb
@@ -0,0 +1,76 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Extensions
+    describe Main do
+      it_should_behave_like "sandboxed rspec_options"
+      before(:each) do
+        @main = Class.new do; include Main; end
+      end
+
+      after(:each) do
+        $rspec_story_steps = @original_rspec_story_steps
+      end
+
+      it "should create an Options object" do
+        @main.send(:rspec_options).should be_instance_of(Spec::Runner::Options)
+        @main.send(:rspec_options).should === $rspec_options
+      end
+  
+      specify {@main.should respond_to(:describe)}
+      specify {@main.should respond_to(:context)}
+
+      it "should raise when no block given to describe" do
+        lambda { @main.describe "foo" }.should raise_error(ArgumentError)
+      end
+
+      it "should raise when no description given to describe" do
+        lambda { @main.describe do; end }.should raise_error(ArgumentError)
+      end
+
+      it "should registered ExampleGroups by default" do
+        example_group = @main.describe("The ExampleGroup") do end
+        rspec_options.example_groups.should include(example_group)
+      end
+
+      it "should not run unregistered ExampleGroups" do
+        example_group = @main.describe("The ExampleGroup") do
+          unregister
+        end
+
+        rspec_options.example_groups.should_not include(example_group)
+      end
+      
+      it "should create a shared ExampleGroup with share_examples_for" do
+        group = @main.share_examples_for "all things" do end
+        group.should be_an_instance_of(Spec::Example::SharedExampleGroup)
+      end
+      
+      describe "#share_as" do
+        before(:each) do
+          $share_as_examples_example_module_number ||= 1
+          $share_as_examples_example_module_number += 1
+          t = Time.new.to_i
+          @group_name = "Group#{$share_as_examples_example_module_number}"
+        end
+
+        it "should create a shared ExampleGroup" do
+          group = @main.share_as @group_name do end
+          group.should be_an_instance_of(Spec::Example::SharedExampleGroup)
+        end
+        
+        it "should create a constant that points to a Module" do
+          group = @main.share_as @group_name do end
+          Object.const_get(@group_name).should equal(group)
+        end
+        
+        it "should bark if you pass it something not-constantizable" do
+          lambda do
+            @group = @main.share_as "Non Constant" do end
+          end.should raise_error(NameError, /The first argument to share_as must be a legal name for a constant/)
+        end
+        
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_that_fails.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_that_fails.rb
new file mode 100644
index 0000000..d6f5564
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_that_fails.rb
@@ -0,0 +1,10 @@
+rspec_lib = File.dirname(__FILE__) + "/../../../../../../lib"
+$:.unshift rspec_lib unless $:.include?(rspec_lib)
+require 'test/unit'
+require 'spec'
+
+describe "example group with failures" do
+  it "should fail" do
+    false.should be_true
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_that_passes.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_that_passes.rb
new file mode 100644
index 0000000..ccd2488
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_that_passes.rb
@@ -0,0 +1,10 @@
+rspec_lib = File.dirname(__FILE__) + "/../../../../../../lib"
+$:.unshift rspec_lib unless $:.include?(rspec_lib)
+require 'test/unit'
+require 'spec'
+
+describe "example group with passing examples" do
+  it "should pass" do
+    true.should be_true
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_with_errors.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_with_errors.rb
new file mode 100644
index 0000000..71427db
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/spec_with_errors.rb
@@ -0,0 +1,10 @@
+rspec_lib = File.dirname(__FILE__) + "/../../../../../../lib"
+$:.unshift rspec_lib unless $:.include?(rspec_lib)
+require 'test/unit'
+require 'spec'
+
+describe "example group with errors" do
+  it "should raise errors" do
+    raise "error raised in example group with errors"
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_that_fails.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_that_fails.rb
new file mode 100644
index 0000000..3fb6515
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_that_fails.rb
@@ -0,0 +1,10 @@
+rspec_lib = File.dirname(__FILE__) + "/../../../../../../lib"
+$:.unshift rspec_lib unless $:.include?(rspec_lib)
+require 'test/unit'
+require 'spec'
+
+class TestCaseThatFails < Test::Unit::TestCase
+  def test_that_fails
+    false.should be_true
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_that_passes.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_that_passes.rb
new file mode 100644
index 0000000..69239c0
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_that_passes.rb
@@ -0,0 +1,10 @@
+rspec_lib = File.dirname(__FILE__) + "/../../../../../../lib"
+$:.unshift rspec_lib unless $:.include?(rspec_lib)
+require 'test/unit'
+require 'spec'
+
+class TestCaseThatPasses < Test::Unit::TestCase
+  def test_that_passes
+    true.should be_true
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_with_errors.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_with_errors.rb
new file mode 100644
index 0000000..35dcb6b
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/test_case_with_errors.rb
@@ -0,0 +1,10 @@
+rspec_lib = File.dirname(__FILE__) + "/../../../../../../lib"
+$:.unshift rspec_lib unless $:.include?(rspec_lib)
+require 'test/unit'
+require 'spec'
+
+class TestCaseWithErrors < Test::Unit::TestCase
+  def test_with_error
+    raise "error raised in TestCaseWithErrors"
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb
new file mode 100644
index 0000000..0c2167a
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb
@@ -0,0 +1,38 @@
+rspec_lib = File.dirname(__FILE__) + "/../../../../../../lib"
+$:.unshift rspec_lib unless $:.include?(rspec_lib)
+require "test/unit"
+require "spec"
+
+module Test
+  module Unit
+    describe TestSuiteAdapter do
+      def create_adapter(group)
+        TestSuiteAdapter.new(group)
+      end
+
+      describe "#size" do
+        it "should return the number of examples in the example group" do
+          group = Class.new(Spec::ExampleGroup) do
+            describe("some examples")
+            it("bar") {}
+            it("baz") {}
+          end
+          adapter = create_adapter(group)
+          adapter.size.should == 2
+        end
+      end
+
+      describe "#delete" do
+        it "should do nothing" do
+          group = Class.new(Spec::ExampleGroup) do
+            describe("Some Examples")
+            it("does something") {}
+          end
+          adapter = create_adapter(group)
+          adapter.delete(adapter.examples.first)
+          adapter.should be_empty
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/spec_spec.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/spec_spec.rb
new file mode 100644
index 0000000..8a1e130
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/spec_spec.rb
@@ -0,0 +1,45 @@
+require File.dirname(__FILE__) + '/test_unit_spec_helper'
+
+describe "ExampleGroup with test/unit/interop" do
+  include TestUnitSpecHelper
+  
+  before(:each) do
+    @dir = File.dirname(__FILE__) + "/resources"
+  end
+  
+  describe "with passing examples" do
+    it "should output 0 failures" do
+      output = ruby("#{@dir}/spec_that_passes.rb")
+      output.should include("1 example, 0 failures")
+    end
+
+    it "should return an exit code of 0" do
+      ruby("#{@dir}/spec_that_passes.rb")
+      $?.should == 0
+    end
+  end
+
+  describe "with failing examples" do
+    it "should output 1 failure" do
+      output = ruby("#{@dir}/spec_that_fails.rb")
+      output.should include("1 example, 1 failure")
+    end
+
+    it "should return an exit code of 256" do
+      ruby("#{@dir}/spec_that_fails.rb")
+      $?.should == 256
+    end
+  end
+
+  describe "with example that raises an error" do
+    it "should output 1 failure" do
+      output = ruby("#{@dir}/spec_with_errors.rb")
+      output.should include("1 example, 1 failure")
+    end
+
+    it "should return an exit code of 256" do
+      ruby("#{@dir}/spec_with_errors.rb")
+      $?.should == 256
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/test_unit_spec_helper.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/test_unit_spec_helper.rb
new file mode 100644
index 0000000..04d5d27
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/test_unit_spec_helper.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/../../../../spec_helper'
+require File.dirname(__FILE__) + '/../../../../ruby_forker'
+
+module TestUnitSpecHelper
+  include RubyForker
+  
+  def run_script(file_name)
+    output = ruby(file_name)
+    if !$?.success? || output.include?("FAILED") || output.include?("Error")
+      raise output
+    end
+    output
+  end  
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/testcase_spec.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/testcase_spec.rb
new file mode 100644
index 0000000..f40111a
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/testcase_spec.rb
@@ -0,0 +1,45 @@
+require File.dirname(__FILE__) + '/test_unit_spec_helper'
+
+describe "Test::Unit::TestCase" do
+  include TestUnitSpecHelper
+  
+  before(:each) do
+    @dir = File.dirname(__FILE__) + "/resources"
+  end
+  
+  describe "with passing test case" do
+    it "should output 0 failures" do
+      output = ruby("#{@dir}/test_case_that_passes.rb")
+      output.should include("1 example, 0 failures")
+    end
+
+    it "should return an exit code of 0" do
+      ruby("#{@dir}/test_case_that_passes.rb")
+      $?.should == 0
+    end
+  end
+
+  describe "with failing test case" do
+    it "should output 1 failure" do
+      output = ruby("#{@dir}/test_case_that_fails.rb")
+      output.should include("1 example, 1 failure")
+    end
+
+    it "should return an exit code of 256" do
+      ruby("#{@dir}/test_case_that_fails.rb")
+      $?.should == 256
+    end
+  end
+
+  describe "with test case that raises an error" do
+    it "should output 1 failure" do
+      output = ruby("#{@dir}/test_case_with_errors.rb")
+      output.should include("1 example, 1 failure")
+    end
+
+    it "should return an exit code of 256" do
+      ruby("#{@dir}/test_case_with_errors.rb")
+      $?.should == 256
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/interop/test/unit/testsuite_adapter_spec.rb b/vendor/gems/rspec/spec/spec/interop/test/unit/testsuite_adapter_spec.rb
new file mode 100644
index 0000000..722126b
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/interop/test/unit/testsuite_adapter_spec.rb
@@ -0,0 +1,9 @@
+require File.dirname(__FILE__) + '/test_unit_spec_helper'
+
+describe "TestSuiteAdapter" do
+  include TestUnitSpecHelper
+  it "should pass" do
+    dir = File.dirname(__FILE__)
+    run_script "#{dir}/resources/testsuite_adapter_spec_with_test_unit.rb"
+  end
+end
\ No newline at end of file
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 0000000..d8452d4
--- /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 0000000..d40036c
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/be_spec.rb
@@ -0,0 +1,224 @@
+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" do
+  it "should pass if actual is true or a set value" do
+    true.should be
+    1.should be
+  end
+
+  it "should fail if actual is false" do
+    lambda {false.should be}.should fail_with("expected if to be satisfied, got false")
+  end
+
+  it "should fail if actual is nil" do
+    lambda {nil.should be}.should fail_with("expected if to be satisfied, got nil")
+  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 0000000..d95aa6d
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/change_spec.rb
@@ -0,0 +1,319 @@
+#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).by_at_least(expected)" do
+  before(:each) do
+    @instance = SomethingExpected.new
+    @instance.some_value = 5
+  end
+
+  it "should pass when attribute is changed by greater than the expected amount" do
+    lambda { @instance.some_value += 2 }.should change(@instance, :some_value).by_at_least(1)
+  end
+  
+  it "should pass when attribute is changed by the expected amount" do
+    lambda { @instance.some_value += 2 }.should change(@instance, :some_value).by_at_least(2)
+  end  
+
+  it "should fail when the attribute is changed by less than the expected amount" do
+    lambda do
+      lambda { @instance.some_value += 1 }.should change(@instance, :some_value).by_at_least(2)
+    end.should fail_with("some_value should have been changed by at least 2, but was changed by 1")
+  end
+
+end
+
+describe "should change{ block }.by_at_least(expected)" do
+  before(:each) do
+    @instance = SomethingExpected.new
+    @instance.some_value = 5
+  end
+
+  it "should pass when attribute is changed by greater than expected amount" do
+    lambda { @instance.some_value += 2 }.should change{@instance.some_value}.by_at_least(1)
+  end
+  
+  it "should pass when attribute is changed by the expected amount" do
+    lambda { @instance.some_value += 2 }.should change{@instance.some_value}.by_at_least(2)
+  end  
+
+  it "should fail when the attribute is changed by less than the unexpected amount" do
+    lambda do
+      lambda { @instance.some_value += 1 }.should change{@instance.some_value}.by_at_least(2)
+    end.should fail_with("result should have been changed by at least 2, but was changed by 1")
+  end
+end
+
+
+describe "should change(actual, message).by_at_most(expected)" do
+  before(:each) do
+    @instance = SomethingExpected.new
+    @instance.some_value = 5
+  end
+
+  it "should pass when attribute is changed by less than the expected amount" do
+    lambda { @instance.some_value += 2 }.should change(@instance, :some_value).by_at_most(3)
+  end
+  
+  it "should pass when attribute is changed by the expected amount" do
+    lambda { @instance.some_value += 2 }.should change(@instance, :some_value).by_at_most(2)
+  end  
+
+  it "should fail when the attribute is changed by greater than the expected amount" do
+    lambda do
+      lambda { @instance.some_value += 2 }.should change(@instance, :some_value).by_at_most(1)
+    end.should fail_with("some_value should have been changed by at most 1, but was changed by 2")
+  end
+
+end
+
+describe "should change{ block }.by_at_most(expected)" do
+  before(:each) do
+    @instance = SomethingExpected.new
+    @instance.some_value = 5
+  end
+
+  it "should pass when attribute is changed by less than expected amount" do
+    lambda { @instance.some_value += 2 }.should change{@instance.some_value}.by_at_most(3)
+  end
+  
+  it "should pass when attribute is changed by the expected amount" do
+    lambda { @instance.some_value += 2 }.should change{@instance.some_value}.by_at_most(2)
+  end  
+
+  it "should fail when the attribute is changed by greater than the unexpected amount" do
+    lambda do
+      lambda { @instance.some_value += 2 }.should change{@instance.some_value}.by_at_most(1)
+    end.should fail_with("result should have been changed by at most 1, but was changed by 2")
+  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 0000000..c494e21
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/description_generation_spec.rb
@@ -0,0 +1,153 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+describe "Matchers should be able to generate their own descriptions" do
+  after(:each) do
+    Spec::Matchers.clear_generated_description
+  end
+
+  it "should == expected" do
+    "this".should == "this"
+    Spec::Matchers.generated_description.should == "should == \"this\""
+  end
+  
+  it "should not == expected" do
+    "this".should_not == "that"
+    Spec::Matchers.generated_description.should == "should not == \"that\""
+  end
+  
+  it "should be empty (arbitrary predicate)" do
+    [].should be_empty
+    Spec::Matchers.generated_description.should == "should be empty"
+  end
+  
+  it "should not be empty (arbitrary predicate)" do
+    [1].should_not be_empty
+    Spec::Matchers.generated_description.should == "should not be empty"
+  end
+  
+  it "should be true" do
+    true.should be_true
+    Spec::Matchers.generated_description.should == "should be true"
+  end
+  
+  it "should be false" do
+    false.should be_false
+    Spec::Matchers.generated_description.should == "should be false"
+  end
+  
+  it "should be nil" do
+    nil.should be_nil
+    Spec::Matchers.generated_description.should == "should be nil"
+  end
+  
+  it "should be > n" do
+    5.should be > 3
+    Spec::Matchers.generated_description.should == "should be > 3"
+  end
+  
+  it "should be predicate arg1, arg2 and arg3" do
+    5.0.should be_between(0,10)
+    Spec::Matchers.generated_description.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)
+    Spec::Matchers.generated_description.should == "should be kind of Fixnum"
+  end
+
+  it "should preserve a proper prefix for be predicate" do
+    5.should be_a_kind_of(Fixnum)
+    Spec::Matchers.generated_description.should == "should be a kind of Fixnum"
+    5.should be_an_instance_of(Fixnum)
+    Spec::Matchers.generated_description.should == "should be an instance of Fixnum"
+  end
+  
+  it "should equal" do
+    expected = "expected"
+    expected.should equal(expected)
+    Spec::Matchers.generated_description.should == "should equal \"expected\""
+  end
+  
+  it "should_not equal" do
+    5.should_not equal(37)
+    Spec::Matchers.generated_description.should == "should not equal 37"
+  end
+  
+  it "should eql" do
+    "string".should eql("string")
+    Spec::Matchers.generated_description.should == "should eql \"string\""
+  end
+  
+  it "should not eql" do
+    "a".should_not eql(:a)
+    Spec::Matchers.generated_description.should == "should not eql :a"
+  end
+  
+  it "should have_key" do
+    {:a => "a"}.should have_key(:a)
+    Spec::Matchers.generated_description.should == "should have key :a"
+  end
+  
+  it "should have n items" do
+    team.should have(3).players
+    Spec::Matchers.generated_description.should == "should have 3 players"
+  end
+  
+  it "should have at least n items" do
+    team.should have_at_least(2).players
+    Spec::Matchers.generated_description.should == "should have at least 2 players"
+  end
+  
+  it "should have at most n items" do
+    team.should have_at_most(4).players
+    Spec::Matchers.generated_description.should == "should have at most 4 players"
+  end
+  
+  it "should include" do
+    [1,2,3].should include(3)
+    Spec::Matchers.generated_description.should == "should include 3"
+  end
+  
+  it "should match" do
+    "this string".should match(/this string/)
+    Spec::Matchers.generated_description.should == "should match /this string/"
+  end
+  
+  it "should raise_error" do
+    lambda { raise }.should raise_error
+    Spec::Matchers.generated_description.should == "should raise Exception"
+  end
+  
+  it "should raise_error with type" do
+    lambda { raise }.should raise_error(RuntimeError)
+    Spec::Matchers.generated_description.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")
+    Spec::Matchers.generated_description.should == "should raise RuntimeError with \"there was an error\""
+  end
+  
+  it "should respond_to" do
+    [].should respond_to(:insert)
+    Spec::Matchers.generated_description.should == "should respond to #insert"
+  end
+  
+  it "should throw symbol" do
+    lambda { throw :what_a_mess }.should throw_symbol
+    Spec::Matchers.generated_description.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)
+    Spec::Matchers.generated_description.should == "should throw :what_a_mess"
+  end
+  
+  def team
+    Class.new do
+      def players
+        [1,2,3]
+      end
+    end.new
+  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 0000000..3f265d7
--- /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 0000000..7667bdc
--- /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 0000000..0a50972
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/exist_spec.rb
@@ -0,0 +1,57 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+class Substance
+  def initialize exists, description
+    @exists = exists
+    @description = description
+  end
+  def exist?
+    @exists
+  end
+  def inspect
+    @description
+  end
+end
+  
+class SubstanceTester
+  include Spec::Matchers
+  def initialize substance
+    @substance = substance
+  end
+  def should_exist
+    @substance.should exist
+  end
+end
+
+describe "should exist," do
+  
+  before(:each) do
+    @real = Substance.new true, 'something real'
+    @imaginary = Substance.new false, 'something imaginary'
+  end
+
+  describe "within an example group" do
+  
+    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
+    
+    it "should pass if target doesn't exist" do
+      lambda { @real.should_not exist }.should fail
+    end
+  end
+
+  describe "outside of an example group" do
+
+    it "should pass if target exists" do
+      real_tester = SubstanceTester.new @real
+      real_tester.should_exist
+    end
+
+  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 0000000..ad4fe6f
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/handler_spec.rb
@@ -0,0 +1,129 @@
+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 rescue nil
+  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
+      
+      it "should explain when the matcher parameter is not a matcher" do
+        begin
+          nonmatcher = mock("nonmatcher")
+          actual = Object.new
+          ExpectationMatcherHandler.handle_matcher(actual, nonmatcher)
+        rescue Spec::Expectations::InvalidMatcherError => e
+        end
+
+        e.message.should =~ /^Expected a matcher, got /
+      end
+    end
+
+    describe NegativeExpectationMatcherHandler, ".handle_matcher" do
+      it "should explain when matcher does not support should_not" do
+        matcher = mock("matcher")
+        matcher.stub!(:matches?)
+        actual = Object.new
+        lambda {
+          NegativeExpectationMatcherHandler.handle_matcher(actual, matcher)
+        }.should fail_with(/Matcher does not support should_not.\n/)
+      end      
+      
+      it "should ask the matcher if it matches" do
+        matcher = mock("matcher")
+        actual = Object.new
+        matcher.stub!(:negative_failure_message)
+        matcher.should_receive(:matches?).with(actual).and_return(false)
+        NegativeExpectationMatcherHandler.handle_matcher(actual, matcher)
+      end
+      
+      it "should explain when the matcher parameter is not a matcher" do
+        begin
+          nonmatcher = mock("nonmatcher")
+          actual = Object.new
+          NegativeExpectationMatcherHandler.handle_matcher(actual, nonmatcher)
+        rescue Spec::Expectations::InvalidMatcherError => e
+        end
+
+        e.message.should =~ /^Expected a matcher, got /
+      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 0000000..47f048e
--- /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 0000000..27083c2
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/have_spec.rb
@@ -0,0 +1,291 @@
+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(1).item when Inflector is defined' do
+  include HaveSpecHelper
+  
+  before do
+    unless Object.const_defined?(:Inflector)
+      class Inflector
+        def self.pluralize(string)
+          string.to_s + 's'
+        end
+      end
+    end
+  end
+  
+  it 'should pluralize the collection name' do
+    owner = create_collection_owner_with(1)
+    owner.should have(1).item
+  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 fail when the number of items IN the collection is not as expected" 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 0000000..f1057f3
--- /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 0000000..f69f7ef
--- /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) does not match 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 does not match (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 0000000..80cc985
--- /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 0000000..1292918
--- /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 example_group_methods.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 0000000..1985df0
--- /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 0000000..7cabf81
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/raise_error_spec.rb
@@ -0,0 +1,191 @@
+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 (NameError)" do
+    lambda {
+      lambda { raise }.should raise_error(NameError)
+    }.should fail_with("expected NameError, got RuntimeError")
+  end
+  
+  it "should fail if another error is raised (NameError)" do
+    lambda {
+      lambda { load "non/existent/file" }.should raise_error(NameError)
+    }.should fail_with(/expected NameError, got #<LoadError/)
+  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 0000000..2cdbbcd
--- /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 0000000..7e8d6f9
--- /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/simple_matcher_spec.rb b/vendor/gems/rspec/spec/spec/matchers/simple_matcher_spec.rb
new file mode 100644
index 0000000..b731af9
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/simple_matcher_spec.rb
@@ -0,0 +1,31 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Matchers
+    describe SimpleMatcher do
+      it "should match pass match arg to block" do
+        actual = nil
+        matcher = simple_matcher("message") do |given| actual = given end
+        matcher.matches?("foo")
+        actual.should == "foo"
+      end
+      
+      it "should provide a stock failure message" do
+        matcher = simple_matcher("thing") do end
+        matcher.matches?("other")
+        matcher.failure_message.should =~ /expected \"thing\" but got \"other\"/
+      end
+      
+      it "should provide a stock negative failure message" do
+        matcher = simple_matcher("thing") do end
+        matcher.matches?("other")
+        matcher.negative_failure_message.should =~ /expected not to get \"thing\", but got \"other\"/
+      end
+      
+      it "should provide a description" do
+        matcher = simple_matcher("thing") do end
+        matcher.description.should =="thing"
+      end
+    end
+  end
+end
\ No newline at end of file
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 0000000..7459565
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/matchers/throw_symbol_spec.rb
@@ -0,0 +1,54 @@
+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 if 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
+      it "should only match NameErrors raised by uncaught throws" do
+        @matcher.matches?(lambda{ sym }).should be_false
+      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 0000000..3f50dcf
--- /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 0000000..2bebbdd
--- /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 0000000..01b133d
--- /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 0000000..f3c5e21
--- /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 0000000..2f7b580
--- /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_10263.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_10263.rb
new file mode 100644
index 0000000..e321922
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_10263.rb
@@ -0,0 +1,24 @@
+describe "Mock" do
+  before do
+    @mock = mock("test mock")
+  end
+  
+  specify "when one example has an expectation (non-mock) inside the block passed to the mock" do
+    @mock.should_receive(:msg) do |b|
+      b.should be_true #this call exposes the problem
+    end
+    @mock.msg(false) rescue nil
+  end
+  
+  specify "then the next example should behave as expected instead of saying" do
+    @mock.should_receive(:foobar)
+    @mock.foobar
+    @mock.rspec_verify
+    begin
+      @mock.foobar
+    rescue Exception => e
+      e.message.should == "Mock 'test mock' received unexpected message :foobar with (no args)"
+    end
+  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 0000000..8a334af
--- /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_15719_spec.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_15719_spec.rb
new file mode 100644
index 0000000..82d49ea
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_15719_spec.rb
@@ -0,0 +1,30 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Mocks
+    describe "mock failure" do
+      
+      it "should tell you when it receives the right message with the wrong args" do
+        m = mock("foo")
+        m.should_receive(:bar).with("message")
+        lambda {
+          m.bar("different message")
+        }.should raise_error(Spec::Mocks::MockExpectationError, %Q{Mock 'foo' expected :bar with ("message") but received it with ("different message")})
+        m.bar("message") # allows the spec to pass
+      end
+
+      it "should tell you when it receives the right message with the wrong args if you stub the method" do
+        pending("fix bug 15719")
+        # NOTE - for whatever reason, if you use a the block style of pending here,
+        # rcov gets unhappy. Don't know why yet.
+        m = mock("foo")
+        m.stub!(:bar)
+        m.should_receive(:bar).with("message")
+        lambda {
+          m.bar("different message")
+        }.should raise_error(Spec::Mocks::MockExpectationError, %Q{Mock 'foo' expected :bar with ("message") but received it with ("different message")})
+        m.bar("message") # allows the spec to pass
+      end
+    end
+  end
+end
\ No newline at end of file
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 0000000..6c9705b
--- /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 0000000..f7edfac
--- /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 0000000..7edc3c0
--- /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 for Object" 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 for mock" 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 0000000..a41df43
--- /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 0000000..db6dcea
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/failing_mock_argument_constraints_spec.rb
@@ -0,0 +1,115 @@
+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)
+        Kernel.stub!(:warn)
+      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 0000000..919da29
--- /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 0000000..23ffd01
--- /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 0000000..85a71e3
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/mock_spec.rb
@@ -0,0 +1,475 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module Spec
+  module Mocks
+    describe Mock do
+
+      before(:each) do
+        @mock = mock("test mock")
+      end
+      
+      after(:each) do
+        @mock.rspec_reset
+      end
+      
+      it "should report line number of expectation of unreceived message" do
+        expected_error_line = __LINE__; @mock.should_receive(:wont_happen).with("x", 3)
+        begin
+          @mock.rspec_verify
+          violated
+        rescue MockExpectationError => e
+          # NOTE - this regexp ended w/ $, but jruby adds extra info at the end of the line
+          e.backtrace[0].should match(/#{File.basename(__FILE__)}:#{expected_error_line}/)
+        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
+        lambda {
+          @mock.rspec_verify
+          violated
+        }.should raise_error(MockExpectationError, "Mock 'test mock' expected :not_expected with (any args) 0 times, but received it once")
+      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")
+        lambda {
+          @mock.rspec_verify
+          violated
+        }.should raise_error(MockExpectationError, "Mock 'test mock' expected :not_expected with (\"unexpected text\") 0 times, but received it once")
+      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")
+        lambda {
+          @mock.something("a","d","c")
+          violated
+        }.should raise_error(MockExpectationError, "Mock 'test mock' expected :something with (\"a\", \"b\", \"c\") but received it with (\"a\", \"d\", \"c\")")
+      end
+           
+      it "should fail if unexpected method called" do
+        lambda {
+          @mock.something("a","b","c")
+          violated
+        }.should raise_error(MockExpectationError, "Mock 'test mock' received unexpected message :something with (\"a\", \"b\", \"c\")")
+      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}
+        lambda {
+          @mock.something false
+        }.should raise_error(MockExpectationError, /Mock 'test mock' received :something but passed block failed with: expected true, got false/)
+      end
+        
+      it "should fail right away when method defined as never is received" do
+        pending "Used to pass (false positive). Which one is wrong, the spec or the actual behavior?"
+
+        @mock.should_receive(:not_expected).never
+        lambda {
+          @mock.not_expected
+        }.should raise_error(MockExpectationError, "Mock 'test mock' expected :not_expected 0 times, but received it 1 times")
+      end
+      
+      it "should eventually fail when method defined as never is received" do
+        @mock.should_receive(:not_expected).never
+        @mock.not_expected
+          
+        lambda {
+          @mock.rspec_verify
+        }.should raise_error(MockExpectationError, "Mock 'test mock' expected :not_expected with (any args) 0 times, but received it once")
+      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)
+        lambda {
+          @mock.something
+        }.should raise_error(RuntimeError, "error message")
+      end
+      
+      it "should raise RuntimeError with passed message" do
+        @mock.should_receive(:something).and_raise("error message")
+        lambda {
+          @mock.something
+        }.should raise_error(RuntimeError, "error message")
+      end
+       
+      it "should not raise when told to if args dont match" do
+        @mock.should_receive(:something).with(2).and_raise(RuntimeError)
+        lambda {
+          @mock.something 1
+        }.should raise_error(MockExpectationError)
+      end
+       
+      it "should throw when told to" do
+        @mock.should_receive(:something).and_throw(:blech)
+        lambda {
+          @mock.something
+        }.should throw_symbol(:blech)
+      end
+      
+      it "should raise when explicit return and block constrained" do
+        lambda {
+          @mock.should_receive(:fruit) do |colour|
+            :strawberry
+          end.and_return :apple
+        }.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())
+        lambda {
+          @mock.something 1
+        }.should raise_error(MockExpectationError, "Mock 'test mock' expected :something with (no args) but received it with (1)")
+      end
+
+      it "should fail when args are expected but none are received" do
+        @mock.should_receive(:something).with(1)
+        lambda {
+          @mock.something
+        }.should raise_error(MockExpectationError, "Mock 'test mock' expected :something with (1) but received it with (no args)")
+      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 0 args multiple times to blocks that take a variable number of arguments" do
+        @mock.should_receive(:yield_back).once.with(no_args()).once.and_yield.
+                                                                    and_yield
+        a = nil
+        b = []
+        @mock.yield_back {|*a| b << a}
+        b.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 one arg 3 times consecutively to blocks that take a variable number of arguments" do
+        @mock.should_receive(:yield_back).once.with(no_args()).once.and_yield(99).
+                                                                    and_yield(43).
+                                                                    and_yield("something fruity")
+        a = nil
+        b = []
+        @mock.yield_back {|*a| b << a}
+        b.should == [[99], [43], ["something fruity"]]
+        @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 many args 3 times consecutively to blocks that take a variable number of arguments" do
+        @mock.should_receive(:yield_back).once.with(no_args()).once.and_yield(99, :green, "go").
+                                                                    and_yield("wait", :amber).
+                                                                    and_yield("stop", 12, :red)
+        a = nil
+        b = []
+        @mock.yield_back {|*a| b << a}
+        b.should == [[99, :green, "go"], ["wait", :amber], ["stop", 12, :red]]
+        @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 single value 3 times consecutively" do
+        @mock.should_receive(:yield_back).once.with(no_args()).once.and_yield(99).
+                                                                    and_yield(43).
+                                                                    and_yield("something fruity")
+        a = nil
+        b = []
+        @mock.yield_back {|a| b << a}
+        b.should == [99, 43, "something fruity"]
+        @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 yield two values 3 times consecutively" do
+        @mock.should_receive(:yield_back).once.with(no_args()).once.and_yield('wha', 'zup').
+                                                                    and_yield('not', 'down').
+                                                                    and_yield(14, 65)
+        a, b = nil
+        c = []
+        @mock.yield_back {|a,b| c << [a, b]}
+        c.should == [['wha', 'zup'], ['not', 'down'], [14, 65]]
+        @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')
+        lambda {
+          @mock.yield_back {|a|}
+        }.should raise_error(MockExpectationError, "Mock 'test mock' yielded |\"wha\", \"zup\"| to block with arity of 1")
+      end
+      
+      it "should fail when calling yielding method consecutively with wrong arity" do
+        @mock.should_receive(:yield_back).once.with(no_args()).once.and_yield('wha', 'zup').
+                                                                    and_yield('down').
+                                                                    and_yield(14, 65)
+        lambda {
+          a, b = nil
+          c = []
+          @mock.yield_back {|a,b| c << [a, b]}
+        }.should raise_error(MockExpectationError, "Mock 'test mock' yielded |\"down\"| to block with arity of 2")
+      end
+      
+      it "should fail when calling yielding method without block" do
+        @mock.should_receive(:yield_back).with(no_args()).once.and_yield('wha', 'zup')
+        lambda {
+          @mock.yield_back
+        }.should raise_error(MockExpectationError, "Mock 'test mock' asked to yield |[\"wha\", \"zup\"]| but no block was passed")
+      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 {
+          @mock.yield_me do |x|
+            raise "Bang"
+          end
+        }.should raise_error(StandardError, "Bang")
+      
+        @mock.rspec_verify
+      end
+      
+      it "should clear expectations after verify" do
+        @mock.should_receive(:foobar)
+        @mock.foobar
+        @mock.rspec_verify
+        lambda {
+          @mock.foobar
+        }.should raise_error(MockExpectationError, "Mock 'test mock' received unexpected message :foobar with (no args)")
+      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
+
+      it "should work even after method_missing starts raising NameErrors instead of NoMethodErrors" do
+        # Object#method_missing throws either NameErrors or NoMethodErrors.
+        #
+        # On a fresh ruby program Object#method_missing: 
+        #  * raises a NoMethodError when called directly
+        #  * raises a NameError when called indirectly
+        #
+        # Once Object#method_missing has been called at least once (on any object)
+        # it starts behaving differently: 
+        #  * raises a NameError when called directly
+        #  * raises a NameError when called indirectly
+        #
+        # There was a bug in Mock#method_missing that relied on the fact
+        # that calling Object#method_missing directly raises a NoMethodError.
+        # This example tests that the bug doesn't exist anymore.
+        
+        
+        # Ensures that method_missing always raises NameErrors.
+        a_method_that_doesnt_exist rescue
+        
+        
+        @mock.should_receive(:foobar)
+        @mock.foobar
+        @mock.rspec_verify
+                
+        lambda { @mock.foobar }.should_not raise_error(NameError)
+        lambda { @mock.foobar }.should raise_error(MockExpectationError)
+      end
+
+      it "should temporarily replace a method stub on a mock" do
+        @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 temporarily replace a method stub on a non-mock" do
+        non_mock = Object.new
+        non_mock.stub!(:msg).and_return(:stub_value)
+        non_mock.should_receive(:msg).with(:arg).and_return(:mock_value)
+        non_mock.msg(:arg).should equal(:mock_value)
+        non_mock.msg.should equal(:stub_value)
+        non_mock.msg.should equal(:stub_value)
+        non_mock.rspec_verify
+      end
+      
+      it "should assign stub return values" do
+        mock = Mock.new('name', :message => :response)
+        mock.message.should == :response
+      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 0000000..3e26b73
--- /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], at return_values[1], at 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], at return_values[1], at 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 0000000..57e8ca3
--- /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 0000000..2c15d5c
--- /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 0000000..0bfab26
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/options_hash_spec.rb
@@ -0,0 +1,45 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Mocks
+    describe "calling :should_receive with an options hash" do
+      it_should_behave_like "sandboxed rspec_options"
+      attr_reader :reporter, :example_group
+      before do
+        @reporter = ::Spec::Runner::Reporter.new(options)
+        @example_group = Class.new(::Spec::Example::ExampleGroup) do
+          plugin_mock_framework
+          describe("Some Examples")
+        end
+        reporter.add_example_group example_group
+      end
+
+      it "should report the file and line submitted with :expected_from" do
+        example_definition = example_group.it "spec" do
+          mock = Spec::Mocks::Mock.new("a mock")
+          mock.should_receive(:message, :expected_from => "/path/to/blah.ext:37")
+          mock.rspec_verify
+        end
+        example = example_group.new(example_definition)
+        
+        reporter.should_receive(:example_finished) do |spec, error|
+          error.backtrace.detect {|line| line =~ /\/path\/to\/blah.ext:37/}.should_not be_nil
+        end
+        example.execute(options, {})
+      end
+
+      it "should use the message supplied with :message" do
+        example_definition = @example_group.it "spec" do
+          mock = Spec::Mocks::Mock.new("a mock")
+          mock.should_receive(:message, :message => "recebi nada")
+          mock.rspec_verify
+        end
+        example = @example_group.new(example_definition)
+        @reporter.should_receive(:example_finished) do |spec, error|
+          error.message.should == "recebi nada"
+        end
+        example.execute(@options, {})
+      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 0000000..d7e5944
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/partial_mock_spec.rb
@@ -0,0 +1,106 @@
+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
+    
+    describe "Partially mocking an object that defines ==, after another mock has been defined" do
+      before(:each) do
+        stub("existing mock", :foo => :foo)
+      end
+      
+      class PartiallyMockedEquals
+        attr_reader :val
+        def initialize(val)
+          @val = val
+        end
+        
+        def ==(other)
+          @val == other.val
+        end
+      end
+      
+      it "should not raise an error when stubbing the object" do
+        o = PartiallyMockedEquals.new :foo
+        lambda { o.stub!(:bar) }.should_not raise_error(NoMethodError)
+      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 0000000..c857d83
--- /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 0000000..6de0a58
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/passing_mock_argument_constraints_spec.rb
@@ -0,0 +1,154 @@
+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")
+        Kernel.stub!(:warn)
+      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
+      
+      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 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 0000000..ba38989
--- /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 0000000..ec24772
--- /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 0000000..d6e23d7
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/mocks/stub_spec.rb
@@ -0,0 +1,181 @@
+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
+        @instance = @class.new
+      end
+
+      it "should return expected value when expected message is received" do
+        @instance.stub!(:msg).and_return(:return_value)
+        @instance.msg.should equal(:return_value)
+        @instance.rspec_verify
+      end
+
+      it "should ignore when expected message is received" do
+        @instance.stub!(:msg)
+        @instance.msg
+        lambda do
+          @instance.rspec_verify
+        end.should_not raise_error
+      end
+
+      it "should ignore when message is received with args" do
+        @instance.stub!(:msg)
+        @instance.msg(:an_arg)
+        lambda do
+          @instance.rspec_verify
+        end.should_not raise_error
+      end
+
+      it "should ignore when expected message is not received" do
+        @instance.stub!(:msg)
+        lambda do
+          @instance.rspec_verify
+        end.should_not raise_error
+      end
+      
+      it "should clear itself when verified" do
+        @instance.stub!(:this_should_go).and_return(:blah)
+        @instance.this_should_go.should == :blah
+        @instance.rspec_verify
+        lambda do
+          @instance.this_should_go
+        end.should raise_error(NameError)
+      end
+
+      it "should return values in order to consecutive calls" do
+        return_values = ["1",2,Object.new]
+        @instance.stub!(:msg).and_return(return_values[0],return_values[1],return_values[2])
+        @instance.msg.should == return_values[0]
+        @instance.msg.should == return_values[1]
+        @instance.msg.should == return_values[2]
+      end
+
+      it "should keep returning last value in consecutive calls" do
+        return_values = ["1",2,Object.new]
+        @instance.stub!(:msg).and_return(return_values[0],return_values[1],return_values[2])
+        @instance.msg.should == return_values[0]
+        @instance.msg.should == return_values[1]
+        @instance.msg.should == return_values[2]
+        @instance.msg.should == return_values[2]
+        @instance.msg.should == return_values[2]
+      end
+
+      it "should revert to original instance method if there is one" do
+        @instance.existing_instance_method.should equal(:original_value)
+        @instance.stub!(:existing_instance_method).and_return(:mock_value)
+        @instance.existing_instance_method.should equal(:mock_value)
+        @instance.rspec_verify
+        @instance.existing_instance_method.should equal(:original_value)
+      end
+      
+      it "should revert to original class method if there is one" 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 yield a specified object" do
+        @instance.stub!(:method_that_yields).and_yield(:yielded_obj)
+        current_value = :value_before
+        @instance.method_that_yields {|val| current_value = val}
+        current_value.should == :yielded_obj
+        @instance.rspec_verify
+      end
+
+      it "should yield multiple times with multiple calls to and_yield" do
+        @instance.stub!(:method_that_yields_multiple_times).and_yield(:yielded_value).
+                                                       and_yield(:another_value)
+        current_value = []
+        @instance.method_that_yields_multiple_times {|val| current_value << val}
+        current_value.should == [:yielded_value, :another_value]
+        @instance.rspec_verify
+      end
+      
+      it "should yield a specified object and return another specified object" do
+        yielded_obj = mock("my mock")
+        yielded_obj.should_receive(:foo).with(:bar)
+        @instance.stub!(:method_that_yields_and_returns).and_yield(yielded_obj).and_return(:baz)
+        @instance.method_that_yields_and_returns { |o| o.foo :bar }.should == :baz
+      end
+
+      it "should throw when told to" do
+        @mock.stub!(:something).and_throw(:up)
+        lambda do
+          @mock.something
+        end.should throw_symbol(:up)
+      end
+      
+      it "should override a pre-existing stub" do
+        @stub.stub!(:existing_instance_method).and_return(:updated_stub_value)
+        @stub.existing_instance_method.should == :updated_stub_value
+      end
+      
+      it "should limit " do
+        @stub.stub!(:foo).with("bar")
+        @stub.should_receive(:foo).with("baz")
+        @stub.foo("bar")
+        @stub.foo("baz")
+      end
+    end
+    
+    describe "A method stub with args" do
+      before(:each) do
+        @stub = Object.new
+        @stub.stub!(:foo).with("bar")
+      end
+
+      it "should not complain if not called" do
+      end
+
+      it "should not complain if called with arg" do
+        @stub.foo("bar")
+      end
+
+      it "should complain if called with no arg" do
+        lambda do
+          @stub.foo
+        end.should raise_error
+      end
+
+      it "should complain if called with other arg" do
+        lambda do
+          @stub.foo("other")
+        end.should raise_error
+      end
+
+      it "should not complain if also mocked w/ different args" do
+        @stub.should_receive(:foo).with("baz")
+        @stub.foo("bar")
+        @stub.foo("baz")
+      end
+
+      it "should complain if also mocked w/ different args AND called w/ a 3rd set of args" do
+        @stub.should_receive(:foo).with("baz")
+        @stub.foo("bar")
+        @stub.foo("baz")
+        lambda do
+          @stub.foo("other")
+        end.should raise_error
+      end
+      
+      it "should support options" do
+        @stub.stub!(:foo, :expected_from => "bar")
+      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 0000000..d07e457
--- /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 0000000..44bfd96
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/package/bin_spec_spec.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+require File.dirname(__FILE__) + '/../../ruby_forker'
+
+describe "The bin/spec script" do
+  include RubyForker
+  
+  it "should have no warnings" do
+    pending "Hangs on JRuby" if PLATFORM =~ /java/
+    spec_path = "#{File.dirname(__FILE__)}/../../../bin/spec"
+
+    output = ruby "-w #{spec_path} --help 2>&1"
+    output.should_not =~ /warning/n
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/runner/class_and_argument_parser_spec.rb b/vendor/gems/rspec/spec/spec/runner/class_and_argument_parser_spec.rb
new file mode 100644
index 0000000..b4e9e7f
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/class_and_argument_parser_spec.rb
@@ -0,0 +1,23 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Runner
+    describe ClassAndArgumentsParser, ".parse" do
+      
+      it "should use a single : to separate class names from arguments" do
+        ClassAndArgumentsParser.parse('Foo').should == ['Foo', nil]
+        ClassAndArgumentsParser.parse('Foo:arg').should == ['Foo', 'arg']
+        ClassAndArgumentsParser.parse('Foo::Bar::Zap:arg').should == ['Foo::Bar::Zap', 'arg']
+        ClassAndArgumentsParser.parse('Foo:arg1,arg2').should == ['Foo', 'arg1,arg2']
+        ClassAndArgumentsParser.parse('Foo::Bar::Zap:arg1,arg2').should == ['Foo::Bar::Zap', 'arg1,arg2']
+        ClassAndArgumentsParser.parse('Foo::Bar::Zap:drb://foo,drb://bar').should == ['Foo::Bar::Zap', 'drb://foo,drb://bar']
+      end
+
+      it "should raise an error when passed an empty string" do
+        lambda do
+          ClassAndArgumentsParser.parse('')
+        end.should raise_error("Couldn't parse \"\"")
+      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 0000000..3c3be8c
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/command_line_spec.rb
@@ -0,0 +1,147 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Runner
+    describe CommandLine, ".run" do
+      it_should_behave_like "sandboxed rspec_options"
+      attr_reader :options, :err, :out
+      before do
+        @err = options.error_stream
+        @out = options.output_stream
+      end
+
+      it "should run directory" do
+        file = File.dirname(__FILE__) + '/../../../examples/pure'
+        Spec::Runner::CommandLine.run(OptionParser.parse([file,"-p","**/*.rb"], @err, @out))
+
+        @out.rewind
+        @out.read.should =~ /\d+ examples, 0 failures, 3 pending/n
+      end
+
+      it "should run file" do
+        file = File.dirname(__FILE__) + '/../../../failing_examples/predicate_example.rb'
+        Spec::Runner::CommandLine.run(OptionParser.parse([file], @err, @out))
+
+        @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'
+
+        lambda {
+          Spec::Runner::CommandLine.run(OptionParser.parse([file], @err, @out))
+        }.should raise_error
+      end
+
+      it "should return true when in --generate-options mode" do
+        # NOTE - this used to say /dev/null but jruby hangs on that for some reason
+        Spec::Runner::CommandLine.run(
+          OptionParser.parse(['--generate-options', '/tmp/foo'], @err, @out)
+        ).should be_true
+      end
+
+      it "should dump even if Interrupt exception is occurred" do
+        example_group = Class.new(::Spec::Example::ExampleGroup) do
+          describe("example_group")
+          it "no error" do
+          end
+
+          it "should interrupt" do
+            raise Interrupt, "I'm interrupting"
+          end
+        end
+
+        options = ::Spec::Runner::Options.new(@err, @out)
+        ::Spec::Runner::Options.should_receive(:new).with(@err, @out).and_return(options)
+        options.reporter.should_receive(:dump)
+        options.add_example_group(example_group)
+
+        Spec::Runner::CommandLine.run(OptionParser.parse([], @err, @out))
+      end
+
+      it "should heckle when options have heckle_runner" do
+        example_group = Class.new(::Spec::Example::ExampleGroup).describe("example_group") do
+          it "no error" do
+          end
+        end
+        options = ::Spec::Runner::Options.new(@err, @out)
+        ::Spec::Runner::Options.should_receive(:new).with(@err, @out).and_return(options)
+        options.add_example_group example_group
+
+        heckle_runner = mock("heckle_runner")
+        heckle_runner.should_receive(:heckle_with)
+        $rspec_mocks.__send__(:mocks).delete(heckle_runner)
+
+        options.heckle_runner = heckle_runner
+        options.add_example_group(example_group)
+
+        Spec::Runner::CommandLine.run(OptionParser.parse([], @err, @out))
+        heckle_runner.rspec_verify
+      end
+
+      it "should run examples backwards if options.reverse is true" do
+        options = ::Spec::Runner::Options.new(@err, @out)
+        ::Spec::Runner::Options.should_receive(:new).with(@err, @out).and_return(options)
+        options.reverse = true
+
+        b1 = Class.new(Spec::Example::ExampleGroup)
+        b2 = Class.new(Spec::Example::ExampleGroup)
+
+        b2.should_receive(:run).ordered
+        b1.should_receive(:run).ordered
+
+        options.add_example_group(b1)
+        options.add_example_group(b2)
+
+        Spec::Runner::CommandLine.run(OptionParser.parse([], @err, @out))
+      end
+
+      it "should pass its ExampleGroup to the reporter" do
+        example_group = Class.new(::Spec::Example::ExampleGroup).describe("example_group") do
+          it "should" do
+          end
+        end
+        options = ::Spec::Runner::Options.new(@err, @out)
+        options.add_example_group(example_group)
+
+        ::Spec::Runner::Options.should_receive(:new).with(@err, @out).and_return(options)
+        options.reporter.should_receive(:add_example_group).with(example_group)
+        
+        Spec::Runner::CommandLine.run(OptionParser.parse([], @err, @out))
+      end
+
+      it "runs only selected Examples when options.examples is set" do
+        options = ::Spec::Runner::Options.new(@err, @out)
+        ::Spec::Runner::Options.should_receive(:new).with(@err, @out).and_return(options)
+
+        options.examples << "example_group should"
+        should_has_run = false
+        should_not_has_run = false
+        example_group = Class.new(::Spec::Example::ExampleGroup).describe("example_group") do
+          it "should" do
+            should_has_run = true
+          end
+          it "should not" do
+            should_not_has_run = true
+          end
+        end
+
+        options.reporter.should_receive(:add_example_group).with(example_group)
+
+        options.add_example_group example_group
+        Spec::Runner::CommandLine.run(OptionParser.parse([], @err, @out))
+
+        should_has_run.should be_true
+        should_not_has_run.should be_false
+      end
+
+      it "sets Spec.run to true" do
+        ::Spec.run = false
+        ::Spec.should_not be_run
+        Spec::Runner::CommandLine.run(OptionParser.parse([], @err, @out))
+        ::Spec.should be_run
+      end
+    end
+  end
+end
\ No newline at end of file
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 0000000..760ec37
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/drb_command_line_spec.rb
@@ -0,0 +1,92 @@
+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(OptionParser.parse(['--version'], err, out))
+
+          err.rewind
+          err.read.should =~ /No server is running/
+        end
+      end    
+    end
+
+    class DrbCommandLineSpec < ::Spec::Example::ExampleGroup
+      describe DrbCommandLine, "with local server"
+
+      class CommandLineForSpec
+        def self.run(argv, stderr, stdout)
+          exit Spec::Runner::CommandLine.run(OptionParser.parse(argv, stderr, stdout))
+        end
+      end
+      
+      unless Config::CONFIG['ruby_install_name'] == 'jruby'
+        before(:all) do
+          DRb.start_service("druby://localhost:8989", CommandLineForSpec)
+          @@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(argv)
+          err, out = StringIO.new, StringIO.new
+          out.instance_eval do
+            def tty?; true end
+          end
+          options = ::Spec::Runner::Options.new(err, out)
+          options.argv = argv
+          Spec::Runner::DrbCommandLine.run(options)
+          out.rewind; out.read
+        end
+      end
+
+    end
+  end
+end
diff --git a/examples/etc/otherfile b/vendor/gems/rspec/spec/spec/runner/empty_file.txt
similarity index 100%
copy from examples/etc/otherfile
copy to vendor/gems/rspec/spec/spec/runner/empty_file.txt
diff --git a/vendor/gems/rspec/spec/spec/runner/examples.txt b/vendor/gems/rspec/spec/spec/runner/examples.txt
new file mode 100644
index 0000000..2fcbd35
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/examples.txt
@@ -0,0 +1,2 @@
+Sir, if you were my husband, I would poison your drink.
+Madam, if you were my wife, I would drink it.
\ No newline at end of file
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 0000000..82e7447
--- /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/failed.txt b/vendor/gems/rspec/spec/spec/runner/failed.txt
new file mode 100644
index 0000000..07c5442
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/failed.txt
@@ -0,0 +1,3 @@
+heckler_spec.rb
+command_line_spec.rb
+reporter_spec.rb
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb
new file mode 100644
index 0000000..a08b6e8
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb
@@ -0,0 +1,44 @@
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'spec/runner/formatter/failing_example_groups_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      describe FailingExampleGroupsFormatter do
+        attr_reader :example_group, :formatter, :io
+
+        before(:each) do
+          @io = StringIO.new
+          options = mock('options')
+          @formatter = FailingExampleGroupsFormatter.new(options, io)
+          @example_group = Class.new(::Spec::Example::ExampleGroup)
+        end
+        
+        it "should add example name for each failure" do
+          formatter.add_example_group(Class.new(ExampleGroup).describe("b 1"))
+          formatter.example_failed("e 1", nil, Reporter::Failure.new(nil, RuntimeError.new))
+          formatter.add_example_group(Class.new(ExampleGroup).describe("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 == "b 1\nb 2\n"
+        end
+        
+        it "should delimit ExampleGroup superclass descriptions with :" do
+          parent_example_group = Class.new(example_group).describe("Parent")
+          child_example_group = Class.new(parent_example_group).describe("#child_method")
+          grand_child_example_group = Class.new(child_example_group).describe("GrandChild")
+
+          formatter.add_example_group(grand_child_example_group)
+          formatter.example_failed("failure", nil, Reporter::Failure.new(nil, RuntimeError.new))
+          io.string.should == "Parent#child_method GrandChild\n"
+        end
+
+        it "should remove druby url, which is used by Spec::Distributed" do
+          @formatter.add_example_group(Class.new(ExampleGroup).describe("something something (druby://99.99.99.99:99)"))
+          @formatter.example_failed("e 1", nil, Reporter::Failure.new(nil, RuntimeError.new))
+          io.string.should == "something something\n"
+        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 0000000..fda64f9
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/failing_examples_formatter_spec.rb
@@ -0,0 +1,33 @@
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'spec/runner/formatter/failing_examples_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      describe FailingExamplesFormatter do
+        before(:each) do
+          @io = StringIO.new
+          options = mock('options')
+          @formatter = FailingExamplesFormatter.new(options, @io)
+        end
+
+        it "should add example name for each failure" do
+          example_group_1 = Class.new(ExampleGroup).describe("A")
+          example_group_2 = Class.new(example_group_1).describe("B")
+
+          @formatter.add_example_group(example_group_1)
+          @formatter.example_failed(example_group_1.it("a1"){}, nil, Reporter::Failure.new(nil, RuntimeError.new))
+          @formatter.add_example_group(example_group_2)
+          @formatter.example_failed(example_group_2.it("b2"){}, nil, Reporter::Failure.new(nil, RuntimeError.new))
+          @formatter.example_failed(example_group_2.it("b3"){}, nil, Reporter::Failure.new(nil, RuntimeError.new))
+          @io.string.should eql(<<-EOF
+A a1
+A B b2
+A B b3
+EOF
+)
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.4.html b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.4.html
new file mode 100644
index 0000000..9cc458f
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.4.html
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+
+    // ]]>
+  </script>
+  <style type="text/css">
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+<div class="example_group">
+  <dl>
+  <dt id="example_group_1">Mocker</dt>
+    <script type="text/javascript">moveProgressBar('5.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to call mock()</span></dd>
+    <script type="text/javascript">makeRed('rspec-header');</script>
+    <script type="text/javascript">makeRed('example_group_1');</script>
+    <script type="text/javascript">moveProgressBar('11.7');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when expected message not received</span>
+      <div class="failure" id="failure_1">
+        <div class="message"><pre>Mock 'poke me' expected :poke with (any args) once, but received it 0 times</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:13:
+./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+./spec/spec/runner/formatter/html_formatter_spec.rb:20:</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should fail when expected message not received</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">12</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">poke me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:poke</span><span class="punct">)</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span>
+<span class="linenum">15</span>  </code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('17.6');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when messages are received out of order</span>
+      <div class="failure" id="failure_2">
+        <div class="message"><pre>Mock 'one two three' received :three out of order</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:22:
+./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+./spec/spec/runner/formatter/html_formatter_spec.rb:20:</pre></div>
+    <pre class="ruby"><code><span class="linenum">20</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:three</span><span class="punct">).</span><span class="ident">ordered</span>
+<span class="linenum">21</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">one</span>
+<span class="offending"><span class="linenum">22</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">three</span></span>
+<span class="linenum">23</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">two</span>
+<span class="linenum">24</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('23.5');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should get yelled at when sending unexpected messages</span>
+      <div class="failure" id="failure_3">
+        <div class="message"><pre>Mock 'don't talk to me' expected :any_message_at_all with (any args) 0 times, but received it once</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:28:
+./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+./spec/spec/runner/formatter/html_formatter_spec.rb:20:</pre></div>
+    <pre class="ruby"><code><span class="linenum">26</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should get yelled at when sending unexpected messages</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">27</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">don't talk to me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">28</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_not_receive</span><span class="punct">(</span><span class="symbol">:any_message_at_all</span><span class="punct">)</span></span>
+<span class="linenum">29</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">any_message_at_all</span>
+<span class="linenum">30</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('29.4');</script>
+    <dd class="spec pending_fixed">
+      <span class="failed_spec_name">has a bug we need to fix</span>
+      <div class="failure" id="failure_4">
+        <div class="message"><pre>Expected pending 'here is the bug' to fail. No Error was raised.</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:33:
+./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+./spec/spec/runner/formatter/html_formatter_spec.rb:20:</pre></div>
+    <pre class="ruby"><code><span class="linenum">31</span>
+<span class="linenum">32</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">has a bug we need to fix</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="offending"><span class="linenum">33</span>    <span class="ident">pending</span> <span class="punct">&quot;</span><span class="string">here is the bug</span><span class="punct">&quot;</span> <span class="keyword">do</span></span>
+<span class="linenum">34</span>      <span class="comment"># Actually, no. It's fixed. This will fail because it passes :-)</span>
+<span class="linenum">35</span>      <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">Bug</span><span class="punct">&quot;)</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_2">Running specs with --diff</dt>
+    <script type="text/javascript">makeRed('example_group_2');</script>
+    <script type="text/javascript">moveProgressBar('35.2');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different strings</span>
+      <div class="failure" id="failure_5">
+        <div class="message"><pre>expected: &quot;RSpec is a\nbehaviour driven development\nframework for Ruby\n&quot;,
+     got: &quot;RSpec is a\nbehavior driven development\nframework for Ruby\n&quot; (using ==)
+Diff:
+@@ -1,4 +1,4 @@
+ RSpec is a
+-behavior driven development
++behaviour driven development
+ framework for Ruby
+</pre></div>
+        <div class="backtrace"><pre>./failing_examples/diffing_spec.rb:13:
+./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+./spec/spec/runner/formatter/html_formatter_spec.rb:20:</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span><span class="ident">framework</span> <span class="keyword">for</span> <span class="constant">Ruby</span>
+<span class="linenum">12</span><span class="constant">EOF</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">usa</span><span class="punct">.</span><span class="ident">should</span> <span class="punct">==</span> <span class="ident">uk</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('41.1');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different objects' pretty representation</span>
+      <div class="failure" id="failure_6">
+        <div class="message"><pre>expected &lt;Animal
+name=bob,
+species=tortoise
+&gt;
+, got &lt;Animal
+name=bob,
+species=giraffe
+&gt;
+ (using .eql?)
+Diff:
+@@ -1,5 +1,5 @@
+ &lt;Animal
+ name=bob,
+-species=giraffe
++species=tortoise
+ &gt;
+</pre></div>
+        <div class="backtrace"><pre>./failing_examples/diffing_spec.rb:34:
+./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+./spec/spec/runner/formatter/html_formatter_spec.rb:20:</pre></div>
+    <pre class="ruby"><code><span class="linenum">32</span>    <span class="ident">expected</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">giraffe</span><span class="punct">&quot;</span>
+<span class="linenum">33</span>    <span class="ident">actual</span>   <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">tortoise</span><span class="punct">&quot;</span>
+<span class="offending"><span class="linenum">34</span>    <span class="ident">expected</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">eql</span><span class="punct">(</span><span class="ident">actual</span><span class="punct">)</span></span>
+<span class="linenum">35</span>  <span class="keyword">end</span>
+<span class="linenum">36</span><span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_3">A consumer of a stub</dt>
+    <script type="text/javascript">moveProgressBar('47.0');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to stub methods on any Object</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_4">A stubbed method on a class</dt>
+    <script type="text/javascript">moveProgressBar('52.9');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should return the stubbed value</span></dd>
+    <script type="text/javascript">moveProgressBar('58.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should revert to the original method after each spec</span></dd>
+    <script type="text/javascript">moveProgressBar('64.7');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_5">A mock</dt>
+    <script type="text/javascript">moveProgressBar('70.5');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub!</span></dd>
+    <script type="text/javascript">moveProgressBar('76.4');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock</span></dd>
+    <script type="text/javascript">moveProgressBar('82.3');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_6">pending example (using pending method)</dt>
+    <script type="text/javascript">makeYellow('example_group_6');</script>
+    <script type="text/javascript">moveProgressBar('88.2');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_7">pending example (with no block)</dt>
+    <script type="text/javascript">makeYellow('example_group_7');</script>
+    <script type="text/javascript">moveProgressBar('94.1');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: Not Yet Implemented&quot; (PENDING: Not Yet Implemented)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_8">pending example (with block for pending)</dt>
+    <script type="text/javascript">makeYellow('example_group_8');</script>
+    <script type="text/javascript">moveProgressBar('100.0');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should have a failing block, passed to pending, reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>x seconds</strong>";</script>
+<script type="text/javascript">document.getElementById('totals').innerHTML = "17 examples, 6 failures, 3 pending";</script>
+</div>
+</div>
+</body>
+</html>
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.5-jruby.html b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.5-jruby.html
new file mode 100644
index 0000000..8bf1ed9
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.5-jruby.html
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+
+    // ]]>
+  </script>
+  <style type="text/css">
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+<div class="example_group">
+  <dl>
+  <dt id="example_group_1">Mocker</dt>
+    <script type="text/javascript">moveProgressBar('5.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to call mock()</span></dd>
+    <script type="text/javascript">makeRed('rspec-header');</script>
+    <script type="text/javascript">makeRed('example_group_1');</script>
+    <script type="text/javascript">moveProgressBar('11.7');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when expected message not received</span>
+      <div class="failure" id="failure_1">
+        <div class="message"><pre>Mock 'poke me' expected :poke with (any args) once, but received it 0 times</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:13:in `should_receive'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:24:in `run'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>  it "should fail when expected message not received" do
+<span class="linenum">12</span>    mock = mock("poke me")
+<span class="offending"><span class="linenum">13</span>    mock.should_receive(:poke)</span>
+<span class="linenum">14</span>  end
+<span class="linenum">15</span>  
+<span class="linenum">16</span><span class="comment"># gem install syntax to get syntax highlighting</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('17.6');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when messages are received out of order</span>
+      <div class="failure" id="failure_2">
+        <div class="message"><pre>Mock 'one two three' received :three out of order</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:22:in `three'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:16:in `instance_eval'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:24:in `run'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">20</span>    mock.should_receive(:three).ordered
+<span class="linenum">21</span>    mock.one
+<span class="offending"><span class="linenum">22</span>    mock.three</span>
+<span class="linenum">23</span>    mock.two
+<span class="linenum">24</span>  end
+<span class="linenum">25</span><span class="comment"># gem install syntax to get syntax highlighting</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('23.5');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should get yelled at when sending unexpected messages</span>
+      <div class="failure" id="failure_3">
+        <div class="message"><pre>Mock 'don't talk to me' expected :any_message_at_all with (any args) 0 times, but received it once</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:28:in `should_not_receive'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:24:in `run'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">26</span>  it "should get yelled at when sending unexpected messages" do
+<span class="linenum">27</span>    mock = mock("don't talk to me")
+<span class="offending"><span class="linenum">28</span>    mock.should_not_receive(:any_message_at_all)</span>
+<span class="linenum">29</span>    mock.any_message_at_all
+<span class="linenum">30</span>  end
+<span class="linenum">31</span><span class="comment"># gem install syntax to get syntax highlighting</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('29.4');</script>
+    <dd class="spec pending_fixed">
+      <span class="failed_spec_name">has a bug we need to fix</span>
+      <div class="failure" id="failure_4">
+        <div class="message"><pre>Expected pending 'here is the bug' to fail. No Error was raised.</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:33:in `pending'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:33:in `instance_eval'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:24:in `run'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">31</span>
+<span class="linenum">32</span>  it "has a bug we need to fix" do
+<span class="offending"><span class="linenum">33</span>    pending "here is the bug" do</span>
+<span class="linenum">34</span>      # Actually, no. It's fixed. This will fail because it passes :-)
+<span class="linenum">35</span>      mock = mock("Bug")
+<span class="linenum">36</span><span class="comment"># gem install syntax to get syntax highlighting</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_2">Running specs with --diff</dt>
+    <script type="text/javascript">makeRed('example_group_2');</script>
+    <script type="text/javascript">moveProgressBar('35.2');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different strings</span>
+      <div class="failure" id="failure_5">
+        <div class="message"><pre>expected: &quot;RSpec is a\nbehaviour driven development\nframework for Ruby\n&quot;,
+     got: &quot;RSpec is a\nbehavior driven development\nframework for Ruby\n&quot; (using ==)
+Diff:
+@@ -1,4 +1,4 @@
+ RSpec is a
+-behavior driven development
++behaviour driven development
+ framework for Ruby
+</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/diffing_spec.rb:13:in `=='
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:24:in `run'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>framework for Ruby
+<span class="linenum">12</span>EOF
+<span class="offending"><span class="linenum">13</span>    usa.should == uk</span>
+<span class="linenum">14</span>  end
+<span class="linenum">15</span>
+<span class="linenum">16</span><span class="comment"># gem install syntax to get syntax highlighting</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('41.1');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different objects' pretty representation</span>
+      <div class="failure" id="failure_6">
+        <div class="message"><pre>expected &lt;Animal
+name=bob,
+species=tortoise
+&gt;
+, got &lt;Animal
+name=bob,
+species=giraffe
+&gt;
+ (using .eql?)
+Diff:
+@@ -1,5 +1,5 @@
+ &lt;Animal
+ name=bob,
+-species=giraffe
++species=tortoise
+ &gt;
+</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/diffing_spec.rb:34:in `should'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/diffing_spec.rb:31:in `instance_eval'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:24:in `run'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/spec/spec/runner/formatter/html_formatter_spec.rb:20:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">32</span>    expected = Animal.new "bob", "giraffe"
+<span class="linenum">33</span>    actual   = Animal.new "bob", "tortoise"
+<span class="offending"><span class="linenum">34</span>    expected.should eql(actual)</span>
+<span class="linenum">35</span>  end
+<span class="linenum">36</span>end
+<span class="linenum">37</span><span class="comment"># gem install syntax to get syntax highlighting</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_3">A consumer of a stub</dt>
+    <script type="text/javascript">moveProgressBar('47.0');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to stub methods on any Object</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_4">A stubbed method on a class</dt>
+    <script type="text/javascript">moveProgressBar('52.9');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should return the stubbed value</span></dd>
+    <script type="text/javascript">moveProgressBar('58.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should revert to the original method after each spec</span></dd>
+    <script type="text/javascript">moveProgressBar('64.7');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_5">A mock</dt>
+    <script type="text/javascript">moveProgressBar('70.5');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub!</span></dd>
+    <script type="text/javascript">moveProgressBar('76.4');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock</span></dd>
+    <script type="text/javascript">moveProgressBar('82.3');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_6">pending example (using pending method)</dt>
+    <script type="text/javascript">makeYellow('example_group_6');</script>
+    <script type="text/javascript">moveProgressBar('88.2');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_7">pending example (with no block)</dt>
+    <script type="text/javascript">makeYellow('example_group_7');</script>
+    <script type="text/javascript">moveProgressBar('94.1');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: Not Yet Implemented&quot; (PENDING: Not Yet Implemented)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_8">pending example (with block for pending)</dt>
+    <script type="text/javascript">makeYellow('example_group_8');</script>
+    <script type="text/javascript">moveProgressBar('100.0');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should have a failing block, passed to pending, reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>x seconds</strong>";</script>
+<script type="text/javascript">document.getElementById('totals').innerHTML = "17 examples, 6 failures, 3 pending";</script>
+</div>
+</div>
+</body>
+</html>
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.5.html b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.5.html
new file mode 100644
index 0000000..cda7226
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.5.html
@@ -0,0 +1,371 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+
+    // ]]>
+  </script>
+  <style type="text/css">
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+<div class="example_group">
+  <dl>
+  <dt id="example_group_1">Mocker</dt>
+    <script type="text/javascript">moveProgressBar('5.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to call mock()</span></dd>
+    <script type="text/javascript">makeRed('rspec-header');</script>
+    <script type="text/javascript">makeRed('example_group_1');</script>
+    <script type="text/javascript">moveProgressBar('11.7');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when expected message not received</span>
+      <div class="failure" id="failure_1">
+        <div class="message"><pre>Mock 'poke me' expected :poke with (any args) once, but received it 0 times</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:13:
+./spec/spec/runner/formatter/html_formatter_spec.rb:17:
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should fail when expected message not received</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">12</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">poke me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:poke</span><span class="punct">)</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span>
+<span class="linenum">15</span>  </code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('17.6');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when messages are received out of order</span>
+      <div class="failure" id="failure_2">
+        <div class="message"><pre>Mock 'one two three' received :three out of order</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:22:
+./spec/spec/runner/formatter/html_formatter_spec.rb:17:
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:</pre></div>
+    <pre class="ruby"><code><span class="linenum">20</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:three</span><span class="punct">).</span><span class="ident">ordered</span>
+<span class="linenum">21</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">one</span>
+<span class="offending"><span class="linenum">22</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">three</span></span>
+<span class="linenum">23</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">two</span>
+<span class="linenum">24</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('23.5');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should get yelled at when sending unexpected messages</span>
+      <div class="failure" id="failure_3">
+        <div class="message"><pre>Mock 'don't talk to me' expected :any_message_at_all with (any args) 0 times, but received it once</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:28:
+./spec/spec/runner/formatter/html_formatter_spec.rb:17:
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:</pre></div>
+    <pre class="ruby"><code><span class="linenum">26</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should get yelled at when sending unexpected messages</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">27</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">don't talk to me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">28</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_not_receive</span><span class="punct">(</span><span class="symbol">:any_message_at_all</span><span class="punct">)</span></span>
+<span class="linenum">29</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">any_message_at_all</span>
+<span class="linenum">30</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('29.4');</script>
+    <dd class="spec pending_fixed">
+      <span class="failed_spec_name">has a bug we need to fix</span>
+      <div class="failure" id="failure_4">
+        <div class="message"><pre>Expected pending 'here is the bug' to fail. No Error was raised.</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:33:
+./spec/spec/runner/formatter/html_formatter_spec.rb:17:
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:</pre></div>
+    <pre class="ruby"><code><span class="linenum">31</span>
+<span class="linenum">32</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">has a bug we need to fix</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="offending"><span class="linenum">33</span>    <span class="ident">pending</span> <span class="punct">&quot;</span><span class="string">here is the bug</span><span class="punct">&quot;</span> <span class="keyword">do</span></span>
+<span class="linenum">34</span>      <span class="comment"># Actually, no. It's fixed. This will fail because it passes :-)</span>
+<span class="linenum">35</span>      <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">Bug</span><span class="punct">&quot;)</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_2">Running specs with --diff</dt>
+    <script type="text/javascript">makeRed('example_group_2');</script>
+    <script type="text/javascript">moveProgressBar('35.2');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different strings</span>
+      <div class="failure" id="failure_5">
+        <div class="message"><pre>expected: &quot;RSpec is a\nbehaviour driven development\nframework for Ruby\n&quot;,
+     got: &quot;RSpec is a\nbehavior driven development\nframework for Ruby\n&quot; (using ==)
+Diff:
+@@ -1,4 +1,4 @@
+ RSpec is a
+-behavior driven development
++behaviour driven development
+ framework for Ruby
+</pre></div>
+        <div class="backtrace"><pre>./failing_examples/diffing_spec.rb:13:
+./spec/spec/runner/formatter/html_formatter_spec.rb:17:
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span><span class="ident">framework</span> <span class="keyword">for</span> <span class="constant">Ruby</span>
+<span class="linenum">12</span><span class="constant">EOF</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">usa</span><span class="punct">.</span><span class="ident">should</span> <span class="punct">==</span> <span class="ident">uk</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('41.1');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different objects' pretty representation</span>
+      <div class="failure" id="failure_6">
+        <div class="message"><pre>expected &lt;Animal
+name=bob,
+species=tortoise
+&gt;
+, got &lt;Animal
+name=bob,
+species=giraffe
+&gt;
+ (using .eql?)
+Diff:
+@@ -1,5 +1,5 @@
+ &lt;Animal
+ name=bob,
+-species=giraffe
++species=tortoise
+ &gt;
+</pre></div>
+        <div class="backtrace"><pre>./failing_examples/diffing_spec.rb:34:
+./spec/spec/runner/formatter/html_formatter_spec.rb:17:
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:13:</pre></div>
+    <pre class="ruby"><code><span class="linenum">32</span>    <span class="ident">expected</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">giraffe</span><span class="punct">&quot;</span>
+<span class="linenum">33</span>    <span class="ident">actual</span>   <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">tortoise</span><span class="punct">&quot;</span>
+<span class="offending"><span class="linenum">34</span>    <span class="ident">expected</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">eql</span><span class="punct">(</span><span class="ident">actual</span><span class="punct">)</span></span>
+<span class="linenum">35</span>  <span class="keyword">end</span>
+<span class="linenum">36</span><span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_3">A consumer of a stub</dt>
+    <script type="text/javascript">moveProgressBar('47.0');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to stub methods on any Object</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_4">A stubbed method on a class</dt>
+    <script type="text/javascript">moveProgressBar('52.9');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should return the stubbed value</span></dd>
+    <script type="text/javascript">moveProgressBar('58.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should revert to the original method after each spec</span></dd>
+    <script type="text/javascript">moveProgressBar('64.7');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_5">A mock</dt>
+    <script type="text/javascript">moveProgressBar('70.5');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub!</span></dd>
+    <script type="text/javascript">moveProgressBar('76.4');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock</span></dd>
+    <script type="text/javascript">moveProgressBar('82.3');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_6">pending example (using pending method)</dt>
+    <script type="text/javascript">makeYellow('example_group_6');</script>
+    <script type="text/javascript">moveProgressBar('88.2');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_7">pending example (with no block)</dt>
+    <script type="text/javascript">makeYellow('example_group_7');</script>
+    <script type="text/javascript">moveProgressBar('94.1');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: Not Yet Implemented&quot; (PENDING: Not Yet Implemented)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_8">pending example (with block for pending)</dt>
+    <script type="text/javascript">makeYellow('example_group_8');</script>
+    <script type="text/javascript">moveProgressBar('100.0');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should have a failing block, passed to pending, reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>x seconds</strong>";</script>
+<script type="text/javascript">document.getElementById('totals').innerHTML = "17 examples, 6 failures, 3 pending";</script>
+</div>
+</div>
+</body>
+</html>
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.6-jruby.html b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.6-jruby.html
new file mode 100644
index 0000000..4666218
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.6-jruby.html
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+
+    // ]]>
+  </script>
+  <style type="text/css">
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+<div class="example_group">
+  <dl>
+  <dt id="example_group_1">Mocker</dt>
+    <script type="text/javascript">moveProgressBar('5.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to call mock()</span></dd>
+    <script type="text/javascript">makeRed('rspec-header');</script>
+    <script type="text/javascript">makeRed('example_group_1');</script>
+    <script type="text/javascript">moveProgressBar('11.7');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when expected message not received</span>
+      <div class="failure" id="failure_1">
+        <div class="message"><pre>Mock 'poke me' expected :poke with (any args) once, but received it 0 times</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:13:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:28:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should fail when expected message not received</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">12</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">poke me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:poke</span><span class="punct">)</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span>
+<span class="linenum">15</span>  </code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('17.6');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when messages are received out of order</span>
+      <div class="failure" id="failure_2">
+        <div class="message"><pre>Mock 'one two three' received :three out of order</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:22:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:16:in `instance_eval'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:28:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">20</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:three</span><span class="punct">).</span><span class="ident">ordered</span>
+<span class="linenum">21</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">one</span>
+<span class="offending"><span class="linenum">22</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">three</span></span>
+<span class="linenum">23</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">two</span>
+<span class="linenum">24</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('23.5');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should get yelled at when sending unexpected messages</span>
+      <div class="failure" id="failure_3">
+        <div class="message"><pre>Mock 'don't talk to me' expected :any_message_at_all with (any args) 0 times, but received it once</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:28:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:28:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">26</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should get yelled at when sending unexpected messages</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">27</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">don't talk to me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">28</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_not_receive</span><span class="punct">(</span><span class="symbol">:any_message_at_all</span><span class="punct">)</span></span>
+<span class="linenum">29</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">any_message_at_all</span>
+<span class="linenum">30</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('29.4');</script>
+    <dd class="spec pending_fixed">
+      <span class="failed_spec_name">has a bug we need to fix</span>
+      <div class="failure" id="failure_4">
+        <div class="message"><pre>Expected pending 'here is the bug' to fail. No Error was raised.</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:33:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/mocking_example.rb:33:in `instance_eval'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:28:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">31</span>
+<span class="linenum">32</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">has a bug we need to fix</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="offending"><span class="linenum">33</span>    <span class="ident">pending</span> <span class="punct">&quot;</span><span class="string">here is the bug</span><span class="punct">&quot;</span> <span class="keyword">do</span></span>
+<span class="linenum">34</span>      <span class="comment"># Actually, no. It's fixed. This will fail because it passes :-)</span>
+<span class="linenum">35</span>      <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">Bug</span><span class="punct">&quot;)</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_2">Running specs with --diff</dt>
+    <script type="text/javascript">makeRed('example_group_2');</script>
+    <script type="text/javascript">moveProgressBar('35.2');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different strings</span>
+      <div class="failure" id="failure_5">
+        <div class="message"><pre>expected: &quot;RSpec is a\nbehaviour driven development\nframework for Ruby\n&quot;,
+     got: &quot;RSpec is a\nbehavior driven development\nframework for Ruby\n&quot; (using ==)
+Diff:
+@@ -1,4 +1,4 @@
+ RSpec is a
+-behavior driven development
++behaviour driven development
+ framework for Ruby
+</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/diffing_spec.rb:13:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/diffing_spec.rb:2:in `instance_eval'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:28:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span><span class="ident">framework</span> <span class="keyword">for</span> <span class="constant">Ruby</span>
+<span class="linenum">12</span><span class="constant">EOF</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">usa</span><span class="punct">.</span><span class="ident">should</span> <span class="punct">==</span> <span class="ident">uk</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('41.1');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different objects' pretty representation</span>
+      <div class="failure" id="failure_6">
+        <div class="message"><pre>expected &lt;Animal
+name=bob,
+species=tortoise
+&gt;
+, got &lt;Animal
+name=bob,
+species=giraffe
+&gt;
+ (using .eql?)
+Diff:
+@@ -1,5 +1,5 @@
+ &lt;Animal
+ name=bob,
+-species=giraffe
++species=tortoise
+ &gt;
+</pre></div>
+        <div class="backtrace"><pre>/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/diffing_spec.rb:34:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./failing_examples/diffing_spec.rb:31:in `instance_eval'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:28:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `chdir'
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:
+/Users/david/projects/ruby/jruby/testsuites/rspec/target/rspec/./spec/spec/runner/formatter/html_formatter_spec.rb:24:in `instance_eval'</pre></div>
+    <pre class="ruby"><code><span class="linenum">32</span>    <span class="ident">expected</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">giraffe</span><span class="punct">&quot;</span>
+<span class="linenum">33</span>    <span class="ident">actual</span>   <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">tortoise</span><span class="punct">&quot;</span>
+<span class="offending"><span class="linenum">34</span>    <span class="ident">expected</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">eql</span><span class="punct">(</span><span class="ident">actual</span><span class="punct">)</span></span>
+<span class="linenum">35</span>  <span class="keyword">end</span>
+<span class="linenum">36</span><span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_3">A consumer of a stub</dt>
+    <script type="text/javascript">moveProgressBar('47.0');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to stub methods on any Object</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_4">A stubbed method on a class</dt>
+    <script type="text/javascript">moveProgressBar('52.9');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should return the stubbed value</span></dd>
+    <script type="text/javascript">moveProgressBar('58.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should revert to the original method after each spec</span></dd>
+    <script type="text/javascript">moveProgressBar('64.7');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_5">A mock</dt>
+    <script type="text/javascript">moveProgressBar('70.5');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub!</span></dd>
+    <script type="text/javascript">moveProgressBar('76.4');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock</span></dd>
+    <script type="text/javascript">moveProgressBar('82.3');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_6">pending example (using pending method)</dt>
+    <script type="text/javascript">makeYellow('example_group_6');</script>
+    <script type="text/javascript">moveProgressBar('88.2');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_7">pending example (with no block)</dt>
+    <script type="text/javascript">makeYellow('example_group_7');</script>
+    <script type="text/javascript">moveProgressBar('94.1');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: Not Yet Implemented&quot; (PENDING: Not Yet Implemented)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_8">pending example (with block for pending)</dt>
+    <script type="text/javascript">makeYellow('example_group_8');</script>
+    <script type="text/javascript">moveProgressBar('100.0');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should have a failing block, passed to pending, reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>x seconds</strong>";</script>
+<script type="text/javascript">document.getElementById('totals').innerHTML = "17 examples, 6 failures, 3 pending";</script>
+</div>
+</div>
+</body>
+</html>
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.6.html b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.6.html
new file mode 100644
index 0000000..511495b
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatted-1.8.6.html
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+
+    // ]]>
+  </script>
+  <style type="text/css">
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+<div class="example_group">
+  <dl>
+  <dt id="example_group_1">Mocker</dt>
+    <script type="text/javascript">moveProgressBar('5.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to call mock()</span></dd>
+    <script type="text/javascript">makeRed('rspec-header');</script>
+    <script type="text/javascript">makeRed('example_group_1');</script>
+    <script type="text/javascript">moveProgressBar('11.7');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when expected message not received</span>
+      <div class="failure" id="failure_1">
+        <div class="message"><pre>Mock 'poke me' expected :poke with (any args) once, but received it 0 times</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:13:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should fail when expected message not received</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">12</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">poke me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:poke</span><span class="punct">)</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span>
+<span class="linenum">15</span>  </code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('17.6');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when messages are received out of order</span>
+      <div class="failure" id="failure_2">
+        <div class="message"><pre>Mock 'one two three' received :three out of order</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:22:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">20</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:three</span><span class="punct">).</span><span class="ident">ordered</span>
+<span class="linenum">21</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">one</span>
+<span class="offending"><span class="linenum">22</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">three</span></span>
+<span class="linenum">23</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">two</span>
+<span class="linenum">24</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('23.5');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should get yelled at when sending unexpected messages</span>
+      <div class="failure" id="failure_3">
+        <div class="message"><pre>Mock 'don't talk to me' expected :any_message_at_all with (any args) 0 times, but received it once</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:28:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">26</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should get yelled at when sending unexpected messages</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">27</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">don't talk to me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">28</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_not_receive</span><span class="punct">(</span><span class="symbol">:any_message_at_all</span><span class="punct">)</span></span>
+<span class="linenum">29</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">any_message_at_all</span>
+<span class="linenum">30</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('29.4');</script>
+    <dd class="spec pending_fixed">
+      <span class="failed_spec_name">has a bug we need to fix</span>
+      <div class="failure" id="failure_4">
+        <div class="message"><pre>Expected pending 'here is the bug' to fail. No Error was raised.</pre></div>
+        
+    <pre class="ruby"><code><span class="linenum">31</span>
+<span class="linenum">32</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">has a bug we need to fix</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="offending"><span class="linenum">33</span>    <span class="ident">pending</span> <span class="punct">&quot;</span><span class="string">here is the bug</span><span class="punct">&quot;</span> <span class="keyword">do</span></span>
+<span class="linenum">34</span>      <span class="comment"># Actually, no. It's fixed. This will fail because it passes :-)</span>
+<span class="linenum">35</span>      <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">Bug</span><span class="punct">&quot;)</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_2">Running specs with --diff</dt>
+    <script type="text/javascript">makeRed('example_group_2');</script>
+    <script type="text/javascript">moveProgressBar('35.2');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different strings</span>
+      <div class="failure" id="failure_5">
+        <div class="message"><pre>expected: &quot;RSpec is a\nbehaviour driven development\nframework for Ruby\n&quot;,
+     got: &quot;RSpec is a\nbehavior driven development\nframework for Ruby\n&quot; (using ==)
+Diff:
+@@ -1,4 +1,4 @@
+ RSpec is a
+-behavior driven development
++behaviour driven development
+ framework for Ruby
+</pre></div>
+        
+    <pre class="ruby"><code><span class="linenum">11</span><span class="ident">framework</span> <span class="keyword">for</span> <span class="constant">Ruby</span>
+<span class="linenum">12</span><span class="constant">EOF</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">usa</span><span class="punct">.</span><span class="ident">should</span> <span class="punct">==</span> <span class="ident">uk</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('41.1');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different objects' pretty representation</span>
+      <div class="failure" id="failure_6">
+        <div class="message"><pre>expected &lt;Animal
+name=bob,
+species=tortoise
+&gt;
+, got &lt;Animal
+name=bob,
+species=giraffe
+&gt;
+ (using .eql?)
+Diff:
+@@ -1,5 +1,5 @@
+ &lt;Animal
+ name=bob,
+-species=giraffe
++species=tortoise
+ &gt;
+</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:33:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">32</span>    <span class="ident">expected</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">giraffe</span><span class="punct">&quot;</span>
+<span class="linenum">33</span>    <span class="ident">actual</span>   <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">tortoise</span><span class="punct">&quot;</span>
+<span class="offending"><span class="linenum">34</span>    <span class="ident">expected</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">eql</span><span class="punct">(</span><span class="ident">actual</span><span class="punct">)</span></span>
+<span class="linenum">35</span>  <span class="keyword">end</span>
+<span class="linenum">36</span><span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_3">A consumer of a stub</dt>
+    <script type="text/javascript">moveProgressBar('47.0');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to stub methods on any Object</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_4">A stubbed method on a class</dt>
+    <script type="text/javascript">moveProgressBar('52.9');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should return the stubbed value</span></dd>
+    <script type="text/javascript">moveProgressBar('58.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should revert to the original method after each spec</span></dd>
+    <script type="text/javascript">moveProgressBar('64.7');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_5">A mock</dt>
+    <script type="text/javascript">moveProgressBar('70.5');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub!</span></dd>
+    <script type="text/javascript">moveProgressBar('76.4');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock</span></dd>
+    <script type="text/javascript">moveProgressBar('82.3');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_6">pending example (using pending method)</dt>
+    <script type="text/javascript">makeYellow('example_group_6');</script>
+    <script type="text/javascript">moveProgressBar('88.2');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_7">pending example (with no block)</dt>
+    <script type="text/javascript">makeYellow('example_group_7');</script>
+    <script type="text/javascript">moveProgressBar('94.1');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: Not Yet Implemented&quot; (PENDING: Not Yet Implemented)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_8">pending example (with block for pending)</dt>
+    <script type="text/javascript">makeYellow('example_group_8');</script>
+    <script type="text/javascript">moveProgressBar('100.0');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should have a failing block, passed to pending, reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>x seconds</strong>";</script>
+<script type="text/javascript">document.getElementById('totals').innerHTML = "17 examples, 6 failures, 3 pending";</script>
+</div>
+</div>
+</body>
+</html>
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 0000000..5ba39f0
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatter_spec.rb
@@ -0,0 +1,66 @@
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'hpricot' # Needed to compare generated with wanted HTML
+require 'spec/runner/formatter/html_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      describe HtmlFormatter do
+        ['--diff', '--dry-run'].each do |opt|
+          def jruby?
+            PLATFORM == 'java'
+          end
+    
+          it "should produce HTML identical to the one we designed manually with #{opt}" do
+            root = File.expand_path(File.dirname(__FILE__) + '/../../../..')
+            suffix = jruby? ? '-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)
+            unless jruby?
+              raise "There should be no absolute paths in html_formatted.html!!" if (expected_html =~ /\/Users/n || expected_html =~ /\/home/n)
+            end
+
+            Dir.chdir(root) do
+              args = ['failing_examples/mocking_example.rb', 'failing_examples/diffing_spec.rb', 'examples/pure/stubbing_example.rb',  'examples/pure/pending_example.rb', '--format', 'html', opt]
+              err = StringIO.new
+              out = StringIO.new
+              CommandLine.run(
+                OptionParser.parse(args, err, out)
+              )
+
+              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
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/profile_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/profile_formatter_spec.rb
new file mode 100644
index 0000000..9818054
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/profile_formatter_spec.rb
@@ -0,0 +1,65 @@
+require File.dirname(__FILE__) + '/../../../spec_helper.rb'
+require 'spec/runner/formatter/profile_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      describe ProfileFormatter do
+        attr_reader :io, :formatter
+        before(:each) do
+          @io = StringIO.new
+          options = mock('options')
+          options.stub!(:colour).and_return(true)
+          @formatter = ProfileFormatter.new(options, io)
+        end
+        
+        it "should print a heading" do
+          formatter.start(0)
+          io.string.should eql("Profiling enabled.\n")
+        end
+        
+        it "should record the current time when starting a new example" do
+          now = Time.now
+          Time.stub!(:now).and_return(now)
+          formatter.example_started('should foo')
+          formatter.instance_variable_get("@time").should == now
+        end
+        
+        it "should correctly record a passed example" do
+          now = Time.now
+          Time.stub!(:now).and_return(now)
+          parent_example_group = Class.new(ExampleGroup).describe('Parent')
+          child_example_group = Class.new(parent_example_group).describe('Child')
+
+          formatter.add_example_group(child_example_group)
+          
+          formatter.example_started('when foo')
+          Time.stub!(:now).and_return(now+1)
+          formatter.example_passed(stub('foo', :description => 'i like ice cream'))
+
+          formatter.start_dump
+          io.string.should include('Parent Child')
+        end
+        
+        it "should sort the results in descending order" do
+          formatter.instance_variable_set("@example_times", [['a', 'a', 0.1], ['b', 'b', 0.3], ['c', 'c', 0.2]])
+          formatter.start_dump
+          formatter.instance_variable_get("@example_times").should == [ ['b', 'b', 0.3], ['c', 'c', 0.2], ['a', 'a', 0.1]]
+        end
+        
+        it "should print the top 10 results" do
+          example_group = Class.new(::Spec::Example::ExampleGroup).describe("ExampleGroup")
+          formatter.add_example_group(example_group)
+          formatter.instance_variable_set("@time", Time.now)
+          
+          15.times do 
+            formatter.example_passed(stub('foo', :description => 'i like ice cream'))
+          end
+          
+          io.should_receive(:print).exactly(10)
+          formatter.start_dump
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
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 0000000..127a617
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_spec.rb
@@ -0,0 +1,127 @@
+require File.dirname(__FILE__) + '/../../../spec_helper.rb'
+require 'spec/runner/formatter/progress_bar_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      describe ProgressBarFormatter do
+        before(:each) do
+          @io = StringIO.new
+          @options = mock('options')
+          @options.stub!(:dry_run).and_return(false)
+          @options.stub!(:colour).and_return(false)
+          @formatter = ProgressBarFormatter.new(@options, @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("example_group", ExampleGroup.new("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
+|)
+        end
+
+        it "should push green dot for passing spec" do
+          @io.should_receive(:tty?).and_return(true)
+          @options.should_receive(:colour).and_return(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)
+          @options.should_receive(:colour).and_return(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)
+          @options.should_receive(:colour).and_return(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)
+          @options.should_receive(:colour).and_return(true)
+          @formatter.example_failed("spec", 98, Reporter::Failure.new("c s", Spec::Example::PendingExampleFixedError.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("example_group", ExampleGroup.new("example"), "message")
+          @formatter.dump_pending
+          @io.string.should =~ /Pending\:\nexample_group example \(message\)\n/
+        end
+      end
+      
+      describe "ProgressBarFormatter outputting to custom out" do
+        before(:each) do
+          @out = mock("out")
+          @options = mock('options')
+          @out.stub!(:puts)
+          @formatter = ProgressBarFormatter.new(@options, @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
+
+      describe ProgressBarFormatter, "dry run" do
+        before(:each) do
+          @io = StringIO.new
+          options = mock('options')
+          options.stub!(:dry_run).and_return(true)
+          @formatter = ProgressBarFormatter.new(options, @io)
+        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/snippet_extractor_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/snippet_extractor_spec.rb
new file mode 100644
index 0000000..4bb2f15
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/snippet_extractor_spec.rb
@@ -0,0 +1,18 @@
+require File.dirname(__FILE__) + '/../../../spec_helper.rb'
+require 'spec/runner/formatter/snippet_extractor'
+
+module Spec
+  module Runner
+    module Formatter
+      describe SnippetExtractor do
+        it "should fall back on a default message when it doesn't understand a line" do
+          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
+          SnippetExtractor.new.lines_around("blech", 8).should == "# Couldn't get snippet for blech"
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb
new file mode 100644
index 0000000..e782254
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb
@@ -0,0 +1,103 @@
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'hpricot' # Needed to compare generated with wanted HTML
+require 'spec/runner/formatter/text_mate_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      describe TextMateFormatter do
+        attr_reader :root, :suffix, :expected_file
+        before do
+          @root = File.expand_path(File.dirname(__FILE__) + '/../../../..')
+          @suffix = jruby? ? '-jruby' : ''
+          @expected_file = File.dirname(__FILE__) + "/text_mate_formatted-#{::VERSION}#{suffix}.html"
+        end
+
+        def jruby?
+          PLATFORM == 'java'
+        end
+
+        def produces_html_identical_to_manually_designed_document(opt)
+          root = File.expand_path(File.dirname(__FILE__) + '/../../../..')
+
+          Dir.chdir(root) do
+            args = [
+              'failing_examples/mocking_example.rb',
+                'failing_examples/diffing_spec.rb',
+                'examples/pure/stubbing_example.rb',
+                'examples/pure/pending_example.rb',
+                '--format',
+                'textmate',
+                opt
+            ]
+            err = StringIO.new
+            out = StringIO.new
+            options = ::Spec::Runner::OptionParser.parse(args, err, out)
+            Spec::Runner::CommandLine.run(options)
+
+            yield(out.string)
+          end          
+        end
+
+        # # Uncomment this spec temporarily in order to overwrite the expected with actual.
+        # # Use with care!!!
+        # describe TextMateFormatter, "functional spec file generator" do
+        #   it "generates a new comparison file" do
+        #     Dir.chdir(root) do
+        #       args = ['failing_examples/mocking_example.rb', 'failing_examples/diffing_spec.rb', 'examples/pure/stubbing_example.rb',  'examples/pure/pending_example.rb', '--format', 'textmate', '--diff']
+        #       err = StringIO.new
+        #       out = StringIO.new
+        #       Spec::Runner::CommandLine.run(
+        #         ::Spec::Runner::OptionParser.parse(args, err, out)
+        #       )
+        #
+        #       seconds = /\d+\.\d+ seconds/
+        #       html = out.string.gsub seconds, 'x seconds'
+        #
+        #       File.open(expected_file, 'w') {|io| io.write(html)}
+        #     end
+        #   end
+        # end
+
+         describe "functional spec using --diff" do
+           it "should produce HTML identical to the one we designed manually with --diff" do
+             produces_html_identical_to_manually_designed_document("--diff") do |html|
+               suffix = jruby? ? '-jruby' : ''
+               expected_file = File.dirname(__FILE__) + "/text_mate_formatted-#{::VERSION}#{suffix}.html"
+               unless File.file?(expected_file)
+                 raise "There is no HTML file with expected content for this platform: #{expected_file}"
+               end
+               expected_html = File.read(expected_file)
+
+               seconds = /\d+\.\d+ seconds/
+               html.gsub! seconds, 'x seconds'
+               expected_html.gsub! seconds, 'x seconds'
+
+               doc = Hpricot(html)
+               backtraces = doc.search("div.backtrace/a")
+               doc.search("div.backtrace").remove
+
+               expected_doc = Hpricot(expected_html)
+               expected_doc.search("div.backtrace").remove
+
+               doc.inner_html.should == expected_doc.inner_html
+
+               backtraces.each do |backtrace_link|
+                 backtrace_link[:href].should include("txmt://open?url=")
+               end
+             end
+           end
+
+         end
+
+         describe "functional spec using --dry-run" do
+           it "should produce HTML identical to the one we designed manually with --dry-run" do
+             produces_html_identical_to_manually_designed_document("--dry-run") do |html, expected_html|
+               html.should =~ /This was a dry-run/m
+             end
+           end
+         end
+      end
+    end
+  end
+end
\ No newline at end of file
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 0000000..7999530
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/specdoc_formatter_spec.rb
@@ -0,0 +1,126 @@
+require File.dirname(__FILE__) + '/../../../spec_helper.rb'
+require 'spec/runner/formatter/specdoc_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      describe SpecdocFormatter do
+        it_should_behave_like "sandboxed rspec_options"
+        attr_reader :io, :options, :formatter, :example_group
+        before(:each) do
+          @io = StringIO.new
+          options.stub!(:dry_run).and_return(false)
+          options.stub!(:colour).and_return(false)
+          @formatter = SpecdocFormatter.new(options, io)
+          @example_group = Class.new(::Spec::Example::ExampleGroup).describe("ExampleGroup")
+        end
+
+        describe "where ExampleGroup has no superclasss with a description" do
+          before do
+            formatter.add_example_group(example_group)
+          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 have_example_group_output("\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 have_example_group_output("\nFinished in 3 seconds\n\n2 examples, 1 failure, 4 pending\n")
+          end
+
+          it "should push ExampleGroup name" do
+            io.string.should eql("\nExampleGroup\n")
+          end
+
+          it "when having an error, should push failing spec name and failure number" do
+            formatter.example_failed(
+            example_group.it("spec"),
+            98,
+            Reporter::Failure.new("c s", RuntimeError.new)
+            )
+            io.string.should have_example_group_output("- spec (ERROR - 98)\n")
+          end
+
+          it "when having an expectation failure, should push failing spec name and failure number" do
+            formatter.example_failed(
+            example_group.it("spec"),
+            98,
+            Reporter::Failure.new("c s", Spec::Expectations::ExpectationNotMetError.new)
+            )
+            io.string.should have_example_group_output("- spec (FAILED - 98)\n")
+          end
+
+          it "should push nothing on start" do
+            formatter.start(5)
+            io.string.should have_example_group_output("")
+          end
+
+          it "should push nothing on start dump" do
+            formatter.start_dump
+            io.string.should have_example_group_output("")
+          end
+
+          it "should push passing spec name" do
+            formatter.example_passed(example_group.it("spec"))
+            io.string.should have_example_group_output("- spec\n")
+          end
+
+          it "should push pending example name and message" do
+            formatter.example_pending('example_group', ExampleGroup.new("example"), 'reason')
+            io.string.should have_example_group_output("- example (PENDING: reason)\n")
+          end
+
+          it "should dump pending" do
+            formatter.example_pending('example_group', ExampleGroup.new("example"), 'reason')
+            io.rewind
+            formatter.dump_pending
+            io.string.should =~ /Pending\:\nexample_group example \(reason\)\n/
+          end
+
+          def have_example_group_output(expected_output)
+            expected = "\nExampleGroup\n#{expected_output}"
+            ::Spec::Matchers::SimpleMatcher.new(expected) do |actual|
+              actual == expected
+            end
+          end
+        end
+
+        describe "where ExampleGroup has two superclasses with a description" do
+          attr_reader :child_example_group, :grand_child_example_group
+          before do
+            @child_example_group = Class.new(example_group).describe("Child ExampleGroup")
+            @grand_child_example_group = Class.new(child_example_group).describe("GrandChild ExampleGroup")
+            formatter.add_example_group(grand_child_example_group)
+          end
+
+          specify "when having an error, should push failing spec name and failure number" do
+            formatter.example_failed(
+              example_group.it("spec"),
+              98,
+              Reporter::Failure.new("c s", RuntimeError.new)
+            )
+            io.string.should have_nested_example_group_output("- spec (ERROR - 98)\n")
+          end
+
+          specify "when having an expectation failure, should push failing spec name and failure number" do
+            formatter.example_failed(
+              example_group.it("spec"),
+              98,
+              Reporter::Failure.new("c s", Spec::Expectations::ExpectationNotMetError.new)
+            )
+            io.string.should have_nested_example_group_output("- spec (FAILED - 98)\n")
+          end
+
+          def have_nested_example_group_output(expected_output)
+            expected_full_output = "\nExampleGroup Child ExampleGroup GrandChild ExampleGroup\n#{expected_output}"
+            ::Spec::Matchers::SimpleMatcher.new(expected_full_output) do |actual|
+              actual == expected_full_output
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/story/html_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/story/html_formatter_spec.rb
new file mode 100644
index 0000000..37fb7c6
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/story/html_formatter_spec.rb
@@ -0,0 +1,61 @@
+require File.dirname(__FILE__) + '/../../../../spec_helper.rb'
+require 'spec/runner/formatter/story/html_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      module Story
+        describe HtmlFormatter do
+          before :each do
+            @out = StringIO.new
+            @options = mock('options')
+            @reporter = HtmlFormatter.new(@options, @out)
+          end
+          
+          it "should just be poked at" do
+            @reporter.run_started(1)
+            @reporter.story_started('story_title', 'narrative')
+
+            @reporter.scenario_started('story_title', 'succeeded_scenario_name')
+            @reporter.step_succeeded('given', 'succeded_step', 'one', 'two')
+            @reporter.scenario_succeeded('story_title', 'succeeded_scenario_name')
+
+            @reporter.scenario_started('story_title', 'pending_scenario_name')
+            @reporter.step_pending('when', 'pending_step', 'un', 'deux')
+            @reporter.scenario_pending('story_title', 'pending_scenario_name', 'not done')
+
+            @reporter.scenario_started('story_title', 'failed_scenario_name')
+            @reporter.step_failed('then', 'failed_step', 'en', 'to')
+            @reporter.scenario_failed('story_title', 'failed_scenario_name', NameError.new('sup'))
+            
+            @reporter.scenario_started('story_title', 'scenario_with_given_scenario_name')
+            @reporter.found_scenario('given scenario', 'succeeded_scenario_name')
+            
+            @reporter.story_ended('story_title', 'narrative')
+            @reporter.run_ended
+          end
+          
+          it "should create spans for params" do
+            @reporter.step_succeeded('given', 'a $coloured $animal', 'brown', 'dog')
+            @out.string.should == "                <li class=\"passed\">Given a <span class=\"param\">brown</span> <span class=\"param\">dog</span></li>\n"
+          end
+          
+          it 'should create spanes for params in regexp steps' do
+            @reporter.step_succeeded :given, /a (pink|blue) (.*)/, 'brown', 'dog'
+            @out.string.should == "                <li class=\"passed\">Given a <span class=\"param\">brown</span> <span class=\"param\">dog</span></li>\n"
+          end
+
+          it "should create a ul for collected_steps" do
+            @reporter.collected_steps(['Given a $coloured $animal', 'Given a $n legged eel'])
+            @out.string.should == (<<-EOF)
+      <ul id="stock_steps" style="display: none;">
+        <li>Given a $coloured $animal</li>
+        <li>Given a $n legged eel</li>
+      </ul>
+EOF
+          end
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb
new file mode 100644
index 0000000..9632b06
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb
@@ -0,0 +1,335 @@
+require File.dirname(__FILE__) + '/../../../../spec_helper.rb'
+require 'spec/runner/formatter/story/plain_text_formatter'
+
+module Spec
+  module Runner
+    module Formatter
+      module Story
+        describe PlainTextFormatter do
+          before :each do
+            # given
+            @out = StringIO.new
+            @tweaker = mock('tweaker')
+            @tweaker.stub!(:tweak_backtrace)
+            @options = mock('options')
+            @options.stub!(:colour).and_return(false)
+            @options.stub!(:backtrace_tweaker).and_return(@tweaker)
+            @formatter = PlainTextFormatter.new(@options, @out)
+          end
+
+          it 'should summarize the number of scenarios when the run ends' do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario2')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario3')
+            @formatter.run_ended
+
+            # then
+            @out.string.should include('3 scenarios')
+          end
+
+          it 'should summarize the number of successful scenarios when the run ends' do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario2')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario3')
+            @formatter.run_ended
+
+            # then
+            @out.string.should include('3 scenarios: 3 succeeded')
+          end
+
+          it 'should summarize the number of failed scenarios when the run ends' do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario2', exception_from { raise RuntimeError, 'oops' })
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario3', exception_from { raise RuntimeError, 'oops' })
+            @formatter.run_ended
+
+            # then
+            @out.string.should include("3 scenarios: 1 succeeded, 2 failed")
+          end
+
+          it 'should end cleanly (no characters on the last line) with successes' do
+            # when
+            @formatter.run_started(1)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario')
+            @formatter.run_ended
+
+            # then
+            @out.string.should =~ /\n\z/
+          end
+
+          it 'should end cleanly (no characters on the last line) with failures' do
+            # when
+            @formatter.run_started(1)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario', exception_from { raise RuntimeError, 'oops' })
+            @formatter.run_ended
+
+            # then
+            @out.string.should =~ /\n\z/
+          end
+
+          it 'should end cleanly (no characters on the last line) with pending steps' do
+            # when
+            @formatter.run_started(1)
+            @formatter.scenario_started(nil, nil)
+            @formatter.step_pending(:then, 'do pend')
+            @formatter.scenario_pending('story', 'scenario', exception_from { raise RuntimeError, 'oops' })
+            @formatter.run_ended
+
+            # then
+            @out.string.should =~ /\n\z/
+          end
+
+          it 'should summarize the number of pending scenarios when the run ends' do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_pending('story', 'scenario2', 'message')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_pending('story', 'scenario3', 'message')
+            @formatter.run_ended
+
+            # then
+            @out.string.should include("3 scenarios: 1 succeeded, 0 failed, 2 pending")
+          end
+
+          it "should only count the first failure in one scenario" do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario2', exception_from { raise RuntimeError, 'oops' })
+            @formatter.scenario_failed('story', 'scenario2', exception_from { raise RuntimeError, 'oops again' })
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario3', exception_from { raise RuntimeError, 'oops' })
+            @formatter.run_ended
+
+            # then
+            @out.string.should include("3 scenarios: 1 succeeded, 2 failed")
+          end
+
+          it "should only count the first pending in one scenario" do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_pending('story', 'scenario2', 'because ...')
+            @formatter.scenario_pending('story', 'scenario2', 'because ...')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_pending('story', 'scenario3', 'because ...')
+            @formatter.run_ended
+
+            # then
+            @out.string.should include("3 scenarios: 1 succeeded, 0 failed, 2 pending")
+          end
+
+          it "should only count a failure before the first pending in one scenario" do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_pending('story', 'scenario2', exception_from { raise RuntimeError, 'oops' })
+            @formatter.scenario_failed('story', 'scenario2', exception_from { raise RuntimeError, 'oops again' })
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario3', exception_from { raise RuntimeError, 'oops' })
+            @formatter.run_ended
+
+            # then
+            @out.string.should include("3 scenarios: 1 succeeded, 1 failed, 1 pending")
+          end
+
+          it 'should produce details of the first failure each failed scenario when the run ends' do
+            # when
+            @formatter.run_started(3)
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_succeeded('story', 'scenario1')
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario2', exception_from { raise RuntimeError, 'oops2' })
+            @formatter.scenario_failed('story', 'scenario2', exception_from { raise RuntimeError, 'oops2 - this one should not appear' })
+            @formatter.scenario_started(nil, nil)
+            @formatter.scenario_failed('story', 'scenario3', exception_from { raise RuntimeError, 'oops3' })
+            @formatter.run_ended
+
+            # then
+            @out.string.should include("FAILURES:\n")
+            @out.string.should include("1) story (scenario2) FAILED")
+            @out.string.should include("RuntimeError: oops2")
+            @out.string.should_not include("RuntimeError: oops2 - this one should not appear")
+            @out.string.should include("2) story (scenario3) FAILED")
+            @out.string.should include("RuntimeError: oops3")
+          end
+
+          it 'should produce details of each pending step when the run ends' do
+            # when
+            @formatter.run_started(2)
+            @formatter.story_started('story 1', 'narrative')
+            @formatter.scenario_started('story 1', 'scenario 1')
+            @formatter.step_pending(:given, 'todo 1', [])
+            @formatter.story_started('story 2', 'narrative')
+            @formatter.scenario_started('story 2', 'scenario 2')
+            @formatter.step_pending(:given, 'todo 2', [])
+            @formatter.run_ended
+
+            # then
+            @out.string.should include("Pending Steps:\n")
+            @out.string.should include("1) story 1 (scenario 1): todo 1")
+            @out.string.should include("2) story 2 (scenario 2): todo 2")
+          end
+
+          it 'should document a story title and narrative' do
+            # when
+            @formatter.story_started 'story', 'narrative'
+
+            # then
+            @out.string.should include("Story: story\n\n  narrative")
+          end
+
+          it 'should document a scenario name' do
+            # when
+            @formatter.scenario_started 'story', 'scenario'
+
+            # then
+            @out.string.should include("\n\n  Scenario: scenario")
+          end
+
+          it 'should document a step by sentence-casing its name' do
+            # when
+            @formatter.step_succeeded :given, 'a context'
+            @formatter.step_succeeded :when, 'an event'
+            @formatter.step_succeeded :then, 'an outcome'
+
+            # then
+            @out.string.should include("\n\n    Given a context\n\n    When an event\n\n    Then an outcome")
+          end
+
+          it 'should document additional givens using And' do
+            # when
+            @formatter.step_succeeded :given, 'step 1'
+            @formatter.step_succeeded :given, 'step 2'
+            @formatter.step_succeeded :given, 'step 3'
+
+            # then
+            @out.string.should include("    Given step 1\n    And step 2\n    And step 3")
+          end
+
+          it 'should document additional events using And' do
+            # when
+            @formatter.step_succeeded :when, 'step 1'
+            @formatter.step_succeeded :when, 'step 2'
+            @formatter.step_succeeded :when, 'step 3'
+
+            # then
+            @out.string.should include("    When step 1\n    And step 2\n    And step 3")
+          end
+
+          it 'should document additional outcomes using And' do
+            # when
+            @formatter.step_succeeded :then, 'step 1'
+            @formatter.step_succeeded :then, 'step 2'
+            @formatter.step_succeeded :then, 'step 3'
+
+            # then
+            @out.string.should include("    Then step 1\n    And step 2\n    And step 3")
+          end
+
+          it 'should document a GivenScenario followed by a Given using And' do
+            # when
+            @formatter.step_succeeded :'given scenario', 'a scenario'
+            @formatter.step_succeeded :given, 'a context'
+
+            # then
+            @out.string.should include("    Given scenario a scenario\n    And a context")
+          end
+
+          it 'should document steps with replaced params' do
+            @formatter.step_succeeded :given, 'a $coloured dog with $n legs', 'pink', 21
+            @out.string.should include("  Given a pink dog with 21 legs")
+          end
+
+          it 'should document regexp steps with replaced params' do
+            @formatter.step_succeeded :given, /a (pink|blue) dog with (.*) legs/, 'pink', 21
+            @out.string.should include("  Given a pink dog with 21 legs")
+          end
+
+          it "should append PENDING for the first pending step" do
+            @formatter.scenario_started('','')
+            @formatter.step_pending(:given, 'a context')
+
+            @out.string.should include('Given a context (PENDING)')
+          end
+
+          it "should append PENDING for pending after already pending" do
+            @formatter.scenario_started('','')
+            @formatter.step_pending(:given, 'a context')
+            @formatter.step_pending(:when, 'I say hey')
+
+            @out.string.should include('When I say hey (PENDING)')
+          end
+
+          it "should append FAILED for the first failiure" do
+            @formatter.scenario_started('','')
+            @formatter.step_failed(:given, 'a context')
+
+            @out.string.should include('Given a context (FAILED)')
+          end
+
+          it "should append SKIPPED for the second failiure" do
+            @formatter.scenario_started('','')
+            @formatter.step_failed(:given, 'a context')
+            @formatter.step_failed(:when, 'I say hey')
+
+            @out.string.should include('When I say hey (SKIPPED)')
+          end
+
+          it "should append SKIPPED for the a failiure after PENDING" do
+            @formatter.scenario_started('','')
+            @formatter.step_pending(:given, 'a context')
+            @formatter.step_failed(:when, 'I say hey')
+
+            @out.string.should include('When I say hey (SKIPPED)')
+          end
+
+          it 'should print some white space after each story' do
+            # when
+            @formatter.story_ended 'title', 'narrative'
+
+            # then
+            @out.string.should include("\n\n")
+          end
+
+          it "should print nothing for collected_steps" do
+            @formatter.collected_steps(['Given a $coloured $animal', 'Given a $n legged eel'])
+            @out.string.should == ("")
+          end
+
+          it "should ignore messages it doesn't care about" do
+            lambda {
+              @formatter.this_method_does_not_exist
+            }.should_not raise_error
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/text_mate_formatted-1.8.4.html b/vendor/gems/rspec/spec/spec/runner/formatter/text_mate_formatted-1.8.4.html
new file mode 100644
index 0000000..3f26374
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/text_mate_formatted-1.8.4.html
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+
+    // ]]>
+  </script>
+  <style type="text/css">
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+<div class="example_group">
+  <dl>
+  <dt id="example_group_1">Mocker</dt>
+    <script type="text/javascript">moveProgressBar('5.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to call mock()</span></dd>
+    <script type="text/javascript">makeRed('rspec-header');</script>
+    <script type="text/javascript">makeRed('example_group_1');</script>
+    <script type="text/javascript">moveProgressBar('11.7');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when expected message not received</span>
+      <div class="failure" id="failure_1">
+        <div class="message"><pre>Mock 'poke me' expected :poke with (any args) once, but received it 0 times</pre></div>
+        <div class="backtrace"><pre><a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/failing_examples/mocking_example.rb&line=13">./failing_examples/mocking_example.rb:13</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=52">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:52</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=48">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:48</a> </pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should fail when expected message not received</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">12</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">poke me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:poke</span><span class="punct">)</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span>
+<span class="linenum">15</span>  </code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('17.6');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when messages are received out of order</span>
+      <div class="failure" id="failure_2">
+        <div class="message"><pre>Mock 'one two three' received :three out of order</pre></div>
+        <div class="backtrace"><pre><a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/failing_examples/mocking_example.rb&line=22">./failing_examples/mocking_example.rb:22</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=52">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:52</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=48">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:48</a> </pre></div>
+    <pre class="ruby"><code><span class="linenum">20</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:three</span><span class="punct">).</span><span class="ident">ordered</span>
+<span class="linenum">21</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">one</span>
+<span class="offending"><span class="linenum">22</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">three</span></span>
+<span class="linenum">23</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">two</span>
+<span class="linenum">24</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('23.5');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should get yelled at when sending unexpected messages</span>
+      <div class="failure" id="failure_3">
+        <div class="message"><pre>Mock 'don't talk to me' expected :any_message_at_all with (any args) 0 times, but received it once</pre></div>
+        <div class="backtrace"><pre><a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/failing_examples/mocking_example.rb&line=28">./failing_examples/mocking_example.rb:28</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=52">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:52</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=48">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:48</a> </pre></div>
+    <pre class="ruby"><code><span class="linenum">26</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should get yelled at when sending unexpected messages</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">27</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">don't talk to me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">28</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_not_receive</span><span class="punct">(</span><span class="symbol">:any_message_at_all</span><span class="punct">)</span></span>
+<span class="linenum">29</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">any_message_at_all</span>
+<span class="linenum">30</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('29.4');</script>
+    <dd class="spec pending_fixed">
+      <span class="failed_spec_name">has a bug we need to fix</span>
+      <div class="failure" id="failure_4">
+        <div class="message"><pre>Expected pending 'here is the bug' to fail. No Error was raised.</pre></div>
+        <div class="backtrace"><pre><a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/failing_examples/mocking_example.rb&line=33">./failing_examples/mocking_example.rb:33</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=52">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:52</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=48">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:48</a> </pre></div>
+    <pre class="ruby"><code><span class="linenum">31</span>
+<span class="linenum">32</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">has a bug we need to fix</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="offending"><span class="linenum">33</span>    <span class="ident">pending</span> <span class="punct">&quot;</span><span class="string">here is the bug</span><span class="punct">&quot;</span> <span class="keyword">do</span></span>
+<span class="linenum">34</span>      <span class="comment"># Actually, no. It's fixed. This will fail because it passes :-)</span>
+<span class="linenum">35</span>      <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">Bug</span><span class="punct">&quot;)</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_2">Running specs with --diff</dt>
+    <script type="text/javascript">makeRed('example_group_2');</script>
+    <script type="text/javascript">moveProgressBar('35.2');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different strings</span>
+      <div class="failure" id="failure_5">
+        <div class="message"><pre>expected: &quot;RSpec is a\nbehaviour driven development\nframework for Ruby\n&quot;,
+     got: &quot;RSpec is a\nbehavior driven development\nframework for Ruby\n&quot; (using ==)
+Diff:
+@@ -1,4 +1,4 @@
+ RSpec is a
+-behavior driven development
++behaviour driven development
+ framework for Ruby
+</pre></div>
+        <div class="backtrace"><pre><a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/failing_examples/diffing_spec.rb&line=13">./failing_examples/diffing_spec.rb:13</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=52">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:52</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=48">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:48</a> </pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span><span class="ident">framework</span> <span class="keyword">for</span> <span class="constant">Ruby</span>
+<span class="linenum">12</span><span class="constant">EOF</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">usa</span><span class="punct">.</span><span class="ident">should</span> <span class="punct">==</span> <span class="ident">uk</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('41.1');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different objects' pretty representation</span>
+      <div class="failure" id="failure_6">
+        <div class="message"><pre>expected &lt;Animal
+name=bob,
+species=tortoise
+&gt;
+, got &lt;Animal
+name=bob,
+species=giraffe
+&gt;
+ (using .eql?)
+Diff:
+@@ -1,5 +1,5 @@
+ &lt;Animal
+ name=bob,
+-species=giraffe
++species=tortoise
+ &gt;
+</pre></div>
+        <div class="backtrace"><pre><a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/failing_examples/diffing_spec.rb&line=34">./failing_examples/diffing_spec.rb:34</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=52">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:52</a> 
+<a href="txmt://open?url=file:///Users/aslakhellesoy/scm/rspec/trunk/rspec/spec/spec/runner/formatter/spec_mate_formatter_spec.rb&line=48">./spec/spec/runner/formatter/spec_mate_formatter_spec.rb:48</a> </pre></div>
+    <pre class="ruby"><code><span class="linenum">32</span>    <span class="ident">expected</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">giraffe</span><span class="punct">&quot;</span>
+<span class="linenum">33</span>    <span class="ident">actual</span>   <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">tortoise</span><span class="punct">&quot;</span>
+<span class="offending"><span class="linenum">34</span>    <span class="ident">expected</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">eql</span><span class="punct">(</span><span class="ident">actual</span><span class="punct">)</span></span>
+<span class="linenum">35</span>  <span class="keyword">end</span>
+<span class="linenum">36</span><span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_3">A consumer of a stub</dt>
+    <script type="text/javascript">moveProgressBar('47.0');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to stub methods on any Object</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_4">A stubbed method on a class</dt>
+    <script type="text/javascript">moveProgressBar('52.9');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should return the stubbed value</span></dd>
+    <script type="text/javascript">moveProgressBar('58.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should revert to the original method after each spec</span></dd>
+    <script type="text/javascript">moveProgressBar('64.7');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_5">A mock</dt>
+    <script type="text/javascript">moveProgressBar('70.5');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub!</span></dd>
+    <script type="text/javascript">moveProgressBar('76.4');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock</span></dd>
+    <script type="text/javascript">moveProgressBar('82.3');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_6">pending example (using pending method)</dt>
+    <script type="text/javascript">makeYellow('example_group_6');</script>
+    <script type="text/javascript">moveProgressBar('88.2');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_7">pending example (with no block)</dt>
+    <script type="text/javascript">makeYellow('example_group_7');</script>
+    <script type="text/javascript">moveProgressBar('94.1');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: Not Yet Implemented&quot; (PENDING: Not Yet Implemented)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_8">pending example (with block for pending)</dt>
+    <script type="text/javascript">makeYellow('example_group_8');</script>
+    <script type="text/javascript">moveProgressBar('100.0');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should have a failing block, passed to pending, reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>x seconds</strong>";</script>
+<script type="text/javascript">document.getElementById('totals').innerHTML = "17 examples, 6 failures, 3 pending";</script>
+</div>
+</div>
+</body>
+</html>
diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html b/vendor/gems/rspec/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html
new file mode 100644
index 0000000..8a2b12e
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>RSpec results</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta http-equiv="Expires" content="-1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <style type="text/css">
+  body {
+    margin: 0;
+    padding: 0;
+    background: #fff;
+    font-size: 80%;
+  }
+  </style>
+</head>
+<body>
+<div class="rspec-report">
+  <script type="text/javascript">
+    // <![CDATA[
+function moveProgressBar(percentDone) {
+  document.getElementById("rspec-header").style.width = percentDone +"%";
+}
+function makeRed(element_id) {
+  document.getElementById(element_id).style.background = '#C40D0D';
+  document.getElementById(element_id).style.color = '#FFFFFF';
+}
+
+function makeYellow(element_id) {
+  if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+  else
+  {
+    document.getElementById(element_id).style.background = '#FAF834';
+    document.getElementById(element_id).style.color = '#000000';
+  }
+}
+
+    // ]]>
+  </script>
+  <style type="text/css">
+#rspec-header {
+  background: #65C400; color: #fff;
+}
+
+.rspec-report h1 {
+  margin: 0px 10px 0px 10px;
+  padding: 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  font-size: 1.8em;
+}
+
+#summary {
+  margin: 0; padding: 5px 10px;
+  font-family: "Lucida Grande", Helvetica, sans-serif;
+  text-align: right;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+}
+
+#summary p {
+  margin: 0 0 0 2px;
+}
+
+#summary #totals {
+  font-size: 1.2em;
+}
+
+.example_group {
+  margin: 0 10px 5px;
+  background: #fff;
+}
+
+dl {
+  margin: 0; padding: 0 0 5px;
+  font: normal 11px "Lucida Grande", Helvetica, sans-serif;
+}
+
+dt {
+  padding: 3px;
+  background: #65C400;
+  color: #fff;
+  font-weight: bold;
+}
+
+dd {
+  margin: 5px 0 5px 5px;
+  padding: 3px 3px 3px 18px;
+}
+
+dd.spec.passed {
+  border-left: 5px solid #65C400;
+  border-bottom: 1px solid #65C400;
+  background: #DBFFB4; color: #3D7700;
+}
+
+dd.spec.failed {
+  border-left: 5px solid #C20000;
+  border-bottom: 1px solid #C20000;
+  color: #C20000; background: #FFFBD3;
+}
+
+dd.spec.not_implemented {
+  border-left: 5px solid #FAF834;
+  border-bottom: 1px solid #FAF834;
+  background: #FCFB98; color: #131313;
+}
+
+dd.spec.pending_fixed {
+  border-left: 5px solid #0000C2;
+  border-bottom: 1px solid #0000C2;
+  color: #0000C2; background: #D3FBFF;
+}
+
+.backtrace {
+  color: #000;
+  font-size: 12px;
+}
+
+a {
+  color: #BE5C00;
+}
+
+/* Ruby code, style similar to vibrant ink */
+.ruby {
+  font-size: 12px;
+  font-family: monospace;
+  color: white;
+  background-color: black;
+  padding: 0.1em 0 0.2em 0;
+}
+
+.ruby .keyword { color: #FF6600; }
+.ruby .constant { color: #339999; }
+.ruby .attribute { color: white; }
+.ruby .global { color: white; }
+.ruby .module { color: white; }
+.ruby .class { color: white; }
+.ruby .string { color: #66FF00; }
+.ruby .ident { color: white; }
+.ruby .method { color: #FFCC00; }
+.ruby .number { color: white; }
+.ruby .char { color: white; }
+.ruby .comment { color: #9933CC; }
+.ruby .symbol { color: white; }
+.ruby .regex { color: #44B4CC; }
+.ruby .punct { color: white; }
+.ruby .escape { color: white; }
+.ruby .interp { color: white; }
+.ruby .expr { color: white; }
+
+.ruby .offending { background-color: gray; }
+.ruby .linenum {
+  width: 75px;
+  padding: 0.1em 1em 0.2em 0;
+  color: #000000;
+  background-color: #FFFBD3;
+}
+
+  </style>
+
+<div id="rspec-header">
+  <h1>RSpec Results</h1>
+
+  <div id="summary">
+    <p id="totals">&nbsp;</p>
+    <p id="duration">&nbsp;</p>
+  </div>
+</div>
+
+<div class="results">
+<div class="example_group">
+  <dl>
+  <dt id="example_group_1">Mocker</dt>
+    <script type="text/javascript">moveProgressBar('5.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to call mock()</span></dd>
+    <script type="text/javascript">makeRed('rspec-header');</script>
+    <script type="text/javascript">makeRed('example_group_1');</script>
+    <script type="text/javascript">moveProgressBar('11.7');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when expected message not received</span>
+      <div class="failure" id="failure_1">
+        <div class="message"><pre>Mock 'poke me' expected :poke with (any args) once, but received it 0 times</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:13:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">11</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should fail when expected message not received</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">12</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">poke me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:poke</span><span class="punct">)</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span>
+<span class="linenum">15</span>  </code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('17.6');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should fail when messages are received out of order</span>
+      <div class="failure" id="failure_2">
+        <div class="message"><pre>Mock 'one two three' received :three out of order</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:22:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">20</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:three</span><span class="punct">).</span><span class="ident">ordered</span>
+<span class="linenum">21</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">one</span>
+<span class="offending"><span class="linenum">22</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">three</span></span>
+<span class="linenum">23</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">two</span>
+<span class="linenum">24</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('23.5');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should get yelled at when sending unexpected messages</span>
+      <div class="failure" id="failure_3">
+        <div class="message"><pre>Mock 'don't talk to me' expected :any_message_at_all with (any args) 0 times, but received it once</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:28:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">26</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">should get yelled at when sending unexpected messages</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="linenum">27</span>    <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">don't talk to me</span><span class="punct">&quot;)</span>
+<span class="offending"><span class="linenum">28</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">should_not_receive</span><span class="punct">(</span><span class="symbol">:any_message_at_all</span><span class="punct">)</span></span>
+<span class="linenum">29</span>    <span class="ident">mock</span><span class="punct">.</span><span class="ident">any_message_at_all</span>
+<span class="linenum">30</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('29.4');</script>
+    <dd class="spec pending_fixed">
+      <span class="failed_spec_name">has a bug we need to fix</span>
+      <div class="failure" id="failure_4">
+        <div class="message"><pre>Expected pending 'here is the bug' to fail. No Error was raised.</pre></div>
+        
+    <pre class="ruby"><code><span class="linenum">31</span>
+<span class="linenum">32</span>  <span class="ident">it</span> <span class="punct">&quot;</span><span class="string">has a bug we need to fix</span><span class="punct">&quot;</span> <span class="keyword">do</span>
+<span class="offending"><span class="linenum">33</span>    <span class="ident">pending</span> <span class="punct">&quot;</span><span class="string">here is the bug</span><span class="punct">&quot;</span> <span class="keyword">do</span></span>
+<span class="linenum">34</span>      <span class="comment"># Actually, no. It's fixed. This will fail because it passes :-)</span>
+<span class="linenum">35</span>      <span class="ident">mock</span> <span class="punct">=</span> <span class="ident">mock</span><span class="punct">(&quot;</span><span class="string">Bug</span><span class="punct">&quot;)</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_2">Running specs with --diff</dt>
+    <script type="text/javascript">makeRed('example_group_2');</script>
+    <script type="text/javascript">moveProgressBar('35.2');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different strings</span>
+      <div class="failure" id="failure_5">
+        <div class="message"><pre>expected: &quot;RSpec is a\nbehaviour driven development\nframework for Ruby\n&quot;,
+     got: &quot;RSpec is a\nbehavior driven development\nframework for Ruby\n&quot; (using ==)
+Diff:
+@@ -1,4 +1,4 @@
+ RSpec is a
+-behavior driven development
++behaviour driven development
+ framework for Ruby
+</pre></div>
+        
+    <pre class="ruby"><code><span class="linenum">11</span><span class="ident">framework</span> <span class="keyword">for</span> <span class="constant">Ruby</span>
+<span class="linenum">12</span><span class="constant">EOF</span>
+<span class="offending"><span class="linenum">13</span>    <span class="ident">usa</span><span class="punct">.</span><span class="ident">should</span> <span class="punct">==</span> <span class="ident">uk</span></span>
+<span class="linenum">14</span>  <span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+    <script type="text/javascript">moveProgressBar('41.1');</script>
+    <dd class="spec failed">
+      <span class="failed_spec_name">should print diff of different objects' pretty representation</span>
+      <div class="failure" id="failure_6">
+        <div class="message"><pre>expected &lt;Animal
+name=bob,
+species=tortoise
+&gt;
+, got &lt;Animal
+name=bob,
+species=giraffe
+&gt;
+ (using .eql?)
+Diff:
+@@ -1,5 +1,5 @@
+ &lt;Animal
+ name=bob,
+-species=giraffe
++species=tortoise
+ &gt;
+</pre></div>
+        <div class="backtrace"><pre>./failing_examples/mocking_example.rb:33:
+./spec/spec/runner/formatter/html_formatter_spec.rb:18:
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:in `chdir'
+./spec/spec/runner/formatter/html_formatter_spec.rb:14:</pre></div>
+    <pre class="ruby"><code><span class="linenum">32</span>    <span class="ident">expected</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">giraffe</span><span class="punct">&quot;</span>
+<span class="linenum">33</span>    <span class="ident">actual</span>   <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">&quot;</span><span class="string">bob</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">tortoise</span><span class="punct">&quot;</span>
+<span class="offending"><span class="linenum">34</span>    <span class="ident">expected</span><span class="punct">.</span><span class="ident">should</span> <span class="ident">eql</span><span class="punct">(</span><span class="ident">actual</span><span class="punct">)</span></span>
+<span class="linenum">35</span>  <span class="keyword">end</span>
+<span class="linenum">36</span><span class="keyword">end</span></code></pre>
+      </div>
+    </dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_3">A consumer of a stub</dt>
+    <script type="text/javascript">moveProgressBar('47.0');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should be able to stub methods on any Object</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_4">A stubbed method on a class</dt>
+    <script type="text/javascript">moveProgressBar('52.9');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should return the stubbed value</span></dd>
+    <script type="text/javascript">moveProgressBar('58.8');</script>
+    <dd class="spec passed"><span class="passed_spec_name">should revert to the original method after each spec</span></dd>
+    <script type="text/javascript">moveProgressBar('64.7');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_5">A mock</dt>
+    <script type="text/javascript">moveProgressBar('70.5');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub!</span></dd>
+    <script type="text/javascript">moveProgressBar('76.4');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock</span></dd>
+    <script type="text/javascript">moveProgressBar('82.3');</script>
+    <dd class="spec passed"><span class="passed_spec_name">can stub! and mock the same message</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_6">pending example (using pending method)</dt>
+    <script type="text/javascript">makeYellow('example_group_6');</script>
+    <script type="text/javascript">moveProgressBar('88.2');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_7">pending example (with no block)</dt>
+    <script type="text/javascript">makeYellow('example_group_7');</script>
+    <script type="text/javascript">moveProgressBar('94.1');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should be reported as &quot;PENDING: Not Yet Implemented&quot; (PENDING: Not Yet Implemented)</span></dd>
+  </dl>
+</div>
+<div class="example_group">
+  <dl>
+  <dt id="example_group_8">pending example (with block for pending)</dt>
+    <script type="text/javascript">makeYellow('example_group_8');</script>
+    <script type="text/javascript">moveProgressBar('100.0');</script>
+    <dd class="spec not_implemented"><span class="not_implemented_spec_name">should have a failing block, passed to pending, reported as &quot;PENDING: for some reason&quot; (PENDING: for some reason)</span></dd>
+  </dl>
+</div>
+<script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>x seconds</strong>";</script>
+<script type="text/javascript">document.getElementById('totals').innerHTML = "17 examples, 6 failures, 3 pending";</script>
+</div>
+</div>
+</body>
+</html>
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 0000000..539d908
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/heckle_runner_spec.rb
@@ -0,0 +1,78 @@
+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)
+      @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", rspec_options).and_return(@heckle)
+      @heckle_class.should_receive(:new).with("Foo::Bar", "two", rspec_options).and_return(@heckle)
+      @heckle_class.should_receive(:new).with("Foo::Zap", "three", rspec_options).and_return(@heckle)
+      @heckle_class.should_receive(:new).with("Foo::Zap", "four", rspec_options).and_return(@heckle)
+
+      heckle_runner = Spec::Runner::HeckleRunner.new("Foo", @heckle_class)
+      heckle_runner.heckle_with
+    end
+
+    it "should heckle all methods in a class" do
+      @heckle_class.should_receive(:new).with("Foo::Bar", "one", rspec_options).and_return(@heckle)
+      @heckle_class.should_receive(:new).with("Foo::Bar", "two", rspec_options).and_return(@heckle)
+
+      heckle_runner = Spec::Runner::HeckleRunner.new("Foo::Bar", @heckle_class)
+      heckle_runner.heckle_with
+    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
+      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", rspec_options).and_return(@heckle)
+
+      heckle_runner = Spec::Runner::HeckleRunner.new("Foo::Bar#two", @heckle_class)
+      heckle_runner.heckle_with
+    end
+
+    it "should heckle specific method in a class (with .)" do
+      @heckle_class.should_receive(:new).with("Foo::Bar", "two", rspec_options).and_return(@heckle)
+
+      heckle_runner = Spec::Runner::HeckleRunner.new("Foo::Bar.two", @heckle_class)
+      heckle_runner.heckle_with
+    end
+  end
+  
+  describe "Heckler" do
+    it "should say yes to tests_pass? if specs pass" do
+      options = mock("options", :null_object => true)
+      options.should_receive(:run_examples).and_return(true)
+      heckler = Spec::Runner::Heckler.new("Foo", nil, options)
+      heckler.tests_pass?.should be_true
+    end
+
+    it "should say no to tests_pass? if specs fail" do
+      options = mock("options", :null_object => true)
+      options.should_receive(:run_examples).and_return(false)
+      heckler = Spec::Runner::Heckler.new("Foo", nil, options)
+      heckler.tests_pass?.should be_false
+    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 0000000..7cf6606
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/heckler_spec.rb
@@ -0,0 +1,13 @@
+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 examples on tests_pass?" do
+      options = Spec::Runner::Options.new(StringIO.new, StringIO.new)
+      options.should_receive(:run_examples).with().and_return(&options.method(:run_examples))
+      heckler = Spec::Runner::Heckler.new('Array', 'push', options)
+      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 0000000..e097f2e
--- /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)
+          @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)
+        @error.backtrace.should_not be_empty
+      end
+
+      it "should leave bin spec" do
+        @error.set_backtrace(["bin/spec:"])
+        @tweaker.tweak_backtrace(@error)
+        @error.backtrace.should_not be_empty
+      end
+
+      it "should not barf on nil backtrace" do
+        lambda do
+          @tweaker.tweak_backtrace(@error)
+        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)
+        @error.backtrace.should include("/a/b/c/d.rb")
+      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 0000000..71619b8
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/option_parser_spec.rb
@@ -0,0 +1,378 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+require 'fileutils'
+
+describe "OptionParser" do
+  before(:each) do
+    @out = StringIO.new
+    @err = StringIO.new
+    @parser = Spec::Runner::OptionParser.new(@err, @out)
+  end
+
+  def parse(args)
+    @parser.parse(args)
+    @parser.options
+  end
+  
+  it "should accept files to include" do
+    options = parse(["--pattern", "foo"])
+    options.filename_pattern.should == "foo"
+  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 if no args" do
+    pending 'A regression since 1.0.8' do
+      options = parse([])
+      @out.rewind
+      @out.read.should match(/Usage: spec \(FILE\|DIRECTORY\|GLOB\)\+ \[options\]/m)
+    end
+  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 do 
+      options = parse(["--format", "Custom::MissingFormatter"]) 
+      options.formatters
+    end.should raise_error(NameError)
+    @err.string.should match(/Couldn't find formatter class Custom::MissingFormatter/n)
+  end
+
+  it "should print version to stdout" do
+    options = parse(["--version"])
+    @out.rewind
+    @out.read.should match(/RSpec-\d+\.\d+\.\d+.*\(build \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 story formatter when format is h" do
+    options = parse(["--format", "h"])
+    options.story_formatters[0].class.should equal(Spec::Runner::Formatter::Story::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 story formatter when format is html" do
+    options = parse(["--format", "html"])
+    options.story_formatters[0].class.should equal(Spec::Runner::Formatter::Story::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"])
+    options.formatters # creates the file
+    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 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
+    Spec::Expectations.differ.should_not be_instance_of(Custom::Differ)
+
+    options = parse(["--diff", "Custom::Differ"])
+    options.parse_diff "Custom::Differ"
+    options.diff_format.should == :custom
+    options.differ_class.should == Custom::Differ
+    Spec::Expectations.differ.should be_instance_of(Custom::Differ)
+  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
+
+  describe "when attempting a focussed spec" do
+    attr_reader :file, :dir
+    before do
+      @original_rspec_options = $rspec_options
+      @file = "#{File.dirname(__FILE__)}/spec_parser/spec_parser_fixture.rb"
+      @dir = File.dirname(file)
+    end
+
+    after do
+      $rspec_options = @original_rspec_options
+    end
+
+    def parse(args)
+      options = super
+      $rspec_options = options
+      options.filename_pattern = "*_fixture.rb"
+      options
+    end
+
+    it "should support --line to identify spec" do
+      options = parse([file, "--line", "13"])
+      options.line_number.should == 13
+      options.examples.should be_empty
+      options.run_examples
+      options.examples.should eql(["d"])
+    end
+
+    it "should fail with error message if file is dir along with --line" do
+      options = parse([dir, "--line", "169"])
+      options.line_number.should == 169
+      options.run_examples
+      @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 does not exist along with --line" do
+      options = parse(["some file", "--line", "169"])
+      proc do
+        options.run_examples
+      end.should raise_error
+    end
+
+    it "should fail with error message if more than one files are specified along with --line" do
+      options = parse([file, file, "--line", "169"])
+      options.run_examples
+      @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
+      options = parse([file, "--example", "some example", "--line", "169"])
+      options.run_examples
+      @err.string.should match(/You cannot use both --line and --example/n)
+    end
+  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
+    options = parse(["--options", File.dirname(__FILE__) + "/spec.opts"])
+    options.diff_format.should_not be_nil
+    options.colour.should be_true
+  end
+
+  it "should default the formatter to ProgressBarFormatter when using options file" do
+    options = parse(["--options", File.dirname(__FILE__) + "/spec.opts"])
+    options.formatters.first.should be_instance_of(::Spec::Runner::Formatter::ProgressBarFormatter)
+  end
+
+  it "should read spaced and multi-line options from file when --options is specified" do
+    options = parse(["--options", File.dirname(__FILE__) + "/spec_spaced.opts"])
+    options.diff_format.should_not be_nil
+    options.colour.should be_true
+    options.formatters.first.should be_instance_of(::Spec::Runner::Formatter::SpecdocFormatter)
+  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 save config to file when -G is specified" do
+    FileUtils.rm 'test.spec.opts' if File.exist?('test.spec.opts')
+    options = parse(["--colour", "-G", "test.spec.opts", "--diff"])
+    IO.read('test.spec.opts').should == "--colour\n--diff\n"
+    FileUtils.rm 'test.spec.opts'
+  end
+
+  it "when --drb is specified, calls DrbCommandLine all of the other ARGV arguments" do
+    options = Spec::Runner::OptionParser.parse([
+      "some/spec.rb", "--diff", "--colour"
+    ], @err, @out)
+    Spec::Runner::DrbCommandLine.should_receive(:run).and_return do |options|
+      options.argv.should == ["some/spec.rb", "--diff", "--colour"]
+    end
+    parse(["some/spec.rb", "--diff", "--drb", "--colour"])
+  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
+    options = parse(["--loadby", 'mtime'])
+    runner = Spec::Runner::ExampleGroupRunner.new(options)
+    Spec::Runner::ExampleGroupRunner.should_receive(:new).
+      with(options).
+      and_return(runner)
+    runner.should_receive(:load_files).with(["most_recent_spec.rb", "command_line_spec.rb"])
+
+    Dir.chdir(File.dirname(__FILE__)) do
+      options.files << 'command_line_spec.rb'
+      options.files << 'most_recent_spec.rb'
+      FileUtils.touch "most_recent_spec.rb"
+      options.run_examples
+      FileUtils.rm "most_recent_spec.rb"
+    end
+  end
+
+  it "should use the standard runner by default" do
+    runner = ::Spec::Runner::ExampleGroupRunner.new(@parser.options)
+    ::Spec::Runner::ExampleGroupRunner.should_receive(:new).
+      with(@parser.options).
+      and_return(runner)
+    options = parse([])
+    options.run_examples
+  end
+
+  it "should use a custom runner when given" do
+    runner = Custom::ExampleGroupRunner.new(@parser.options, nil)
+    Custom::ExampleGroupRunner.should_receive(:new).
+      with(@parser.options, nil).
+      and_return(runner)
+    options = parse(["--runner", "Custom::ExampleGroupRunner"])
+    options.run_examples
+  end
+
+  it "should use a custom runner with extra options" do
+    runner = Custom::ExampleGroupRunner.new(@parser.options, 'something')
+    Custom::ExampleGroupRunner.should_receive(:new).
+      with(@parser.options, 'something').
+      and_return(runner)
+    options = parse(["--runner", "Custom::ExampleGroupRunner:something"])
+    options.run_examples
+  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 0000000..6f08937
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/options_spec.rb
@@ -0,0 +1,364 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Runner
+    describe Options do
+      before(:each) do
+        @err = StringIO.new('')
+        @out = StringIO.new('')
+        @options = Options.new(@err, @out)
+      end
+
+      after(:each) do
+        Spec::Expectations.differ = nil
+      end
+
+      describe "#examples" do
+        it "should default to empty array" do
+          @options.examples.should == []
+        end
+      end
+      
+      describe "#include_pattern" do
+        it "should default to '**/*_spec.rb'" do
+          @options.filename_pattern.should == "**/*_spec.rb"
+        end
+      end
+      
+      describe "#files_to_load" do
+        
+        it "should load files not following pattern if named explicitly" do
+          file = File.expand_path(File.dirname(__FILE__) + "/resources/a_bar.rb")
+          @options.files << file
+          @options.files_to_load.should include(file)
+        end
+        
+        describe "with default --pattern" do
+          it "should load files named _spec.rb" do
+            dir = File.expand_path(File.dirname(__FILE__) + "/resources/")
+            @options.files << dir
+            @options.files_to_load.should == ["#{dir}/a_spec.rb"]
+          end
+        end
+        
+        describe "with explicit pattern (single)" do
+          before(:each) do
+            @options.filename_pattern = "**/*_foo.rb"
+          end
+        
+          it "should load files following pattern" do
+            file = File.expand_path(File.dirname(__FILE__) + "/resources/a_foo.rb")
+            @options.files << file
+            @options.files_to_load.should include(file)
+          end
+        
+          it "should load files in directories following pattern" do
+            dir = File.expand_path(File.dirname(__FILE__) + "/resources")
+            @options.files << dir
+            @options.files_to_load.should include("#{dir}/a_foo.rb")
+          end
+        
+          it "should not load files in directories not following pattern" do
+            dir = File.expand_path(File.dirname(__FILE__) + "/resources")
+            @options.files << dir
+            @options.files_to_load.should_not include("#{dir}/a_bar.rb")
+          end
+        end
+        
+        describe "with explicit pattern (comma,separated,values)" do
+          
+          before(:each) do
+            @options.filename_pattern = "**/*_foo.rb,**/*_bar.rb"
+          end
+
+          it "should support comma separated values" do
+            dir = File.expand_path(File.dirname(__FILE__) + "/resources")
+            @options.files << dir
+            @options.files_to_load.should include("#{dir}/a_foo.rb")
+            @options.files_to_load.should include("#{dir}/a_bar.rb")
+          end
+        
+          it "should support comma separated values with spaces" do
+            dir = File.expand_path(File.dirname(__FILE__) + "/resources")
+            @options.files << dir
+            @options.files_to_load.should include("#{dir}/a_foo.rb")
+            @options.files_to_load.should include("#{dir}/a_bar.rb")
+          end
+        
+        end
+      
+      end
+
+      describe "#backtrace_tweaker" do
+        it "should default to QuietBacktraceTweaker" do
+          @options.backtrace_tweaker.class.should == QuietBacktraceTweaker
+        end
+      end
+
+      describe "#dry_run" do
+        it "should default to false" do
+          @options.dry_run.should == false
+        end
+      end
+
+      describe "#context_lines" do
+        it "should default to 3" do
+          @options.context_lines.should == 3
+        end
+      end
+
+      describe "#parse_diff with nil" do
+        before(:each) do
+          @options.parse_diff nil
+        end
+
+        it "should make diff_format unified" do
+          @options.diff_format.should == :unified
+        end
+
+        it "should set Spec::Expectations.differ to be a default differ" do
+          Spec::Expectations.differ.class.should ==
+            ::Spec::Expectations::Differs::Default
+        end
+      end
+
+      describe "#parse_diff with 'unified'" do
+        before(:each) do
+          @options.parse_diff 'unified'
+        end
+
+        it "should make diff_format unified and uses default differ_class" do
+          @options.diff_format.should == :unified
+          @options.differ_class.should equal(Spec::Expectations::Differs::Default)
+        end
+
+        it "should set Spec::Expectations.differ to be a default differ" do
+          Spec::Expectations.differ.class.should ==
+            ::Spec::Expectations::Differs::Default
+        end
+      end
+
+      describe "#parse_diff with 'context'" do
+        before(:each) do
+          @options.parse_diff 'context'
+        end
+
+        it "should make diff_format context and uses default differ_class" do
+          @options.diff_format.should == :context
+          @options.differ_class.should == Spec::Expectations::Differs::Default
+        end
+
+        it "should set Spec::Expectations.differ to be a default differ" do
+          Spec::Expectations.differ.class.should ==
+            ::Spec::Expectations::Differs::Default
+        end
+      end
+
+      describe "#parse_diff with Custom::Differ" do
+        before(:each) do
+          @options.parse_diff 'Custom::Differ'
+        end
+
+        it "should use custom differ_class" do
+          @options.diff_format.should == :custom
+          @options.differ_class.should == Custom::Differ
+          Spec::Expectations.differ.should be_instance_of(Custom::Differ)
+        end
+
+        it "should set Spec::Expectations.differ to be a default differ" do
+          Spec::Expectations.differ.class.should ==
+            ::Custom::Differ
+        end
+      end
+
+      describe "#parse_diff with missing class name" do
+        it "should raise error" do
+          lambda { @options.parse_diff "Custom::MissingDiffer" }.should raise_error(NameError)
+          @err.string.should match(/Couldn't find differ class Custom::MissingDiffer/n)
+        end
+      end
+
+      describe "#parse_example" do
+        it "with argument thats not a file path, sets argument as the example" do
+          example = "something or other"
+          File.file?(example).should == false
+          @options.parse_example example
+          @options.examples.should eql(["something or other"])
+        end
+
+        it "with argument that is a file path, sets examples to contents of the 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 "#examples_should_not_be_run" do
+        it "should cause #run_examples to return true and do nothing" do
+          @options.examples_should_not_be_run
+          ExampleGroupRunner.should_not_receive(:new)
+
+          @options.run_examples.should be_true
+        end
+      end
+
+      describe "#load_class" do
+        it "should raise error when not class name" do
+          lambda do
+            @options.send(:load_class, 'foo', 'fruit', '--food')
+          end.should raise_error('"foo" is not a valid class name')
+        end
+      end
+
+      describe "#reporter" do
+        it "returns a Reporter" do
+          @options.reporter.should be_instance_of(Reporter)
+          @options.reporter.options.should === @options
+        end
+      end
+
+      describe "#add_example_group affecting passed in example_group" do
+        it "runs all examples when options.examples is nil" do
+          example_1_has_run = false
+          example_2_has_run = false
+          @example_group = Class.new(::Spec::Example::ExampleGroup).describe("Some Examples") do
+            it "runs 1" do
+              example_1_has_run = true
+            end
+            it "runs 2" do
+              example_2_has_run = true
+            end
+          end
+
+          @options.examples = nil
+
+          @options.add_example_group @example_group
+          @options.run_examples
+          example_1_has_run.should be_true
+          example_2_has_run.should be_true
+        end
+
+        it "keeps all example_definitions when options.examples is empty" do
+          example_1_has_run = false
+          example_2_has_run = false
+          @example_group = Class.new(::Spec::Example::ExampleGroup).describe("Some Examples") do
+            it "runs 1" do
+              example_1_has_run = true
+            end
+            it "runs 2" do
+              example_2_has_run = true
+            end
+          end
+
+          @options.examples = []
+
+          @options.add_example_group @example_group
+          @options.run_examples
+          example_1_has_run.should be_true
+          example_2_has_run.should be_true
+        end
+      end
+
+      describe "#add_example_group affecting example_group" do
+        it "adds example_group when example_group has example_definitions and is not shared" do
+          @example_group = Class.new(::Spec::Example::ExampleGroup).describe("Some Examples") do
+            it "uses this example_group" do
+            end
+          end
+
+          @options.number_of_examples.should == 0
+          @options.add_example_group @example_group
+          @options.number_of_examples.should == 1
+          @options.example_groups.length.should == 1
+        end
+      end
+
+      describe "#remove_example_group" do
+        it "should remove the ExampleGroup from the list of ExampleGroups" do
+          @example_group = Class.new(::Spec::Example::ExampleGroup).describe("Some Examples") do
+          end
+          @options.add_example_group @example_group
+          @options.example_groups.should include(@example_group)
+
+          @options.remove_example_group @example_group
+          @options.example_groups.should_not include(@example_group)
+        end
+      end
+
+      describe "#run_examples" do
+        it "should use the standard runner by default" do
+          runner = ::Spec::Runner::ExampleGroupRunner.new(@options)
+          ::Spec::Runner::ExampleGroupRunner.should_receive(:new).
+            with(@options).
+            and_return(runner)
+          @options.user_input_for_runner = nil
+
+          @options.run_examples
+        end
+
+        it "should use a custom runner when given" do
+          runner = Custom::ExampleGroupRunner.new(@options, nil)
+          Custom::ExampleGroupRunner.should_receive(:new).
+            with(@options, nil).
+            and_return(runner)
+          @options.user_input_for_runner = "Custom::ExampleGroupRunner"
+
+          @options.run_examples
+        end
+
+        it "should use a custom runner with extra options" do
+          runner = Custom::ExampleGroupRunner.new(@options, 'something')
+          Custom::ExampleGroupRunner.should_receive(:new).
+            with(@options, 'something').
+            and_return(runner)
+          @options.user_input_for_runner = "Custom::ExampleGroupRunner:something"
+
+          @options.run_examples
+        end
+
+        describe "when there are examples" do
+          before(:each) do
+            @options.add_example_group Class.new(::Spec::Example::ExampleGroup)
+            @options.formatters << Formatter::BaseTextFormatter.new(@options, @out)
+          end
+
+          it "runs the Examples and outputs the result" do
+            @options.run_examples
+            @out.string.should include("0 examples, 0 failures")
+          end
+
+          it "sets #examples_run? to true" do
+            @options.examples_run?.should be_false
+            @options.run_examples
+            @options.examples_run?.should be_true
+          end
+        end
+
+        describe "when there are no examples" do
+          before(:each) do
+            @options.formatters << Formatter::BaseTextFormatter.new(@options, @out)
+          end
+
+          it "does not run Examples and does not output a result" do
+            @options.run_examples
+            @out.string.should_not include("examples")
+            @out.string.should_not include("failures")
+          end
+
+          it "sets #examples_run? to false" do
+            @options.examples_run?.should be_false
+            @options.run_examples
+            @options.examples_run?.should be_false
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/runner/output_one_time_fixture.rb b/vendor/gems/rspec/spec/spec/runner/output_one_time_fixture.rb
new file mode 100644
index 0000000..444730d
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/output_one_time_fixture.rb
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+describe "Running an Example" do
+  it "should not output twice" do
+    true.should be_true
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/runner/output_one_time_fixture_runner.rb b/vendor/gems/rspec/spec/spec/runner/output_one_time_fixture_runner.rb
new file mode 100644
index 0000000..a0e6131
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/output_one_time_fixture_runner.rb
@@ -0,0 +1,8 @@
+dir = File.dirname(__FILE__)
+require "#{dir}/../../spec_helper"
+
+triggering_double_output = rspec_options
+options = Spec::Runner::OptionParser.parse(
+  ["#{dir}/output_one_time_fixture.rb"], $stderr, $stdout
+)
+Spec::Runner::CommandLine.run(options)
diff --git a/vendor/gems/rspec/spec/spec/runner/output_one_time_spec.rb b/vendor/gems/rspec/spec/spec/runner/output_one_time_spec.rb
new file mode 100644
index 0000000..8f67a38
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/output_one_time_spec.rb
@@ -0,0 +1,16 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Runner
+    describe CommandLine do
+      it "should not output twice" do
+        dir = File.dirname(__FILE__)
+        Dir.chdir("#{dir}/../../..") do
+          output =`ruby #{dir}/output_one_time_fixture_runner.rb`
+          output.should include("1 example, 0 failures")
+          output.should_not include("0 examples, 0 failures")
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
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 0000000..e47b6c7
--- /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)
+        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)
+        @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)
+          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)
+        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)
+        @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)
+        @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 0000000..52377e7
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/reporter_spec.rb
@@ -0,0 +1,189 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+module Spec
+  module Runner
+    describe Reporter do
+      attr_reader :formatter_output, :options, :backtrace_tweaker, :formatter, :reporter, :example_group
+      before(:each) do
+        @formatter_output = StringIO.new
+        @options = Options.new(StringIO.new, StringIO.new)
+        @backtrace_tweaker = stub("backtrace tweaker", :tweak_backtrace => nil)
+        options.backtrace_tweaker = backtrace_tweaker
+        @formatter = ::Spec::Runner::Formatter::BaseTextFormatter.new(options, formatter_output)
+        options.formatters << formatter
+        @reporter = Reporter.new(options)
+        @example_group = create_example_group("example_group")
+        reporter.add_example_group example_group
+      end
+
+      def failure
+        Mocks::DuckTypeArgConstraint.new(:header, :exception)
+      end
+
+      def create_example_group(description_text)
+        example_group = Class.new(Spec::Example::ExampleGroup)
+        example_group.describe description_text
+        example_group
+      end
+
+      it "should assign itself as the reporter to options" do
+        options.reporter.should equal(@reporter)
+      end
+
+      it "should tell formatter when example_group is added" do
+        formatter.should_receive(:add_example_group).with(example_group)
+        reporter.add_example_group(example_group)
+      end
+
+      it "should handle multiple example_groups with same name" do
+        formatter.should_receive(:add_example_group).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(:dump_pending)
+        formatter.should_receive(:close).with(no_args)
+        formatter.should_receive(:dump_summary).with(anything(), 3, 0, 0)
+        reporter.add_example_group(create_example_group("example_group"))
+        reporter.example_started("spec 1")
+        reporter.example_finished("spec 1")
+        reporter.add_example_group(create_example_group("example_group"))
+        reporter.example_started("spec 2")
+        reporter.example_finished("spec 2")
+        reporter.add_example_group(create_example_group("example_group"))
+        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
+        passing = ExampleGroup.new("example")
+        failing = ExampleGroup.new("example")
+
+        formatter.should_receive(:add_example_group).exactly(2).times
+        formatter.should_receive(:example_passed).with(passing).exactly(2).times
+        formatter.should_receive(:example_failed).with(failing, 1, failure)
+        formatter.should_receive(:example_failed).with(failing, 2, failure)
+        formatter.should_receive(:dump_failure).exactly(2).times
+        formatter.should_receive(:start_dump)
+        formatter.should_receive(:dump_pending)
+        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_example_group(create_example_group("example_group"))
+        reporter.example_finished(passing)
+        reporter.example_finished(failing, error)
+
+        reporter.add_example_group(create_example_group("example_group"))
+        reporter.example_finished(passing)
+        reporter.example_finished(failing, error)
+        reporter.dump
+      end
+
+      it "should push stats to formatter even with no data" do
+        formatter.should_receive(:start_dump)
+        formatter.should_receive(:dump_pending)
+        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(:dump_pending)
+        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
+
+      describe Reporter, "reporting one passing example" do
+        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_pending)
+          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
+        it "should tell formatter that example failed" do
+          formatter.should_receive(:example_failed)
+          reporter.example_finished(example_group, RuntimeError.new)
+        end
+
+        it "should delegate to backtrace tweaker" do
+          formatter.should_receive(:example_failed)
+          backtrace_tweaker.should_receive(:tweak_backtrace)
+          reporter.example_finished(ExampleGroup.new("example"), RuntimeError.new)
+        end
+
+        it "should account for failing example in stats" do
+          example = ExampleGroup.new("example")
+          formatter.should_receive(:example_failed).with(example, 1, failure)
+          formatter.should_receive(:start_dump)
+          formatter.should_receive(:dump_pending)
+          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.example_finished(example, RuntimeError.new)
+          reporter.dump
+        end
+
+      end
+
+      describe Reporter, "reporting one pending example (ExamplePendingError)" do
+        it "should tell formatter example is pending" do
+          example = ExampleGroup.new("example")
+          formatter.should_receive(:example_pending).with(example_group.description, example, "reason")
+          formatter.should_receive(:add_example_group).with(example_group)
+          reporter.add_example_group(example_group)
+          reporter.example_finished(example, Spec::Example::ExamplePendingError.new("reason"))
+        end
+
+        it "should account for pending example in stats" do
+          example = ExampleGroup.new("example")
+          formatter.should_receive(:example_pending).with(example_group.description, example, "reason")
+          formatter.should_receive(:start_dump)
+          formatter.should_receive(:dump_pending)
+          formatter.should_receive(:dump_summary).with(anything(), 1, 0, 1)
+          formatter.should_receive(:close).with(no_args)
+          formatter.should_receive(:add_example_group).with(example_group)
+          reporter.add_example_group(example_group)
+          reporter.example_finished(example, Spec::Example::ExamplePendingError.new("reason"))
+          reporter.dump
+        end
+      end
+
+      describe Reporter, "reporting one pending example (PendingExampleFixedError)" do
+        it "should tell formatter pending example is fixed" do
+          formatter.should_receive(:example_failed) do |name, counter, failure|
+            failure.header.should == "'example_group example' FIXED"
+          end
+          formatter.should_receive(:add_example_group).with(example_group)
+          reporter.add_example_group(example_group)
+          reporter.example_finished(ExampleGroup.new("example"), Spec::Example::PendingExampleFixedError.new("reason"))
+        end
+      end
+    end
+  end
+end
diff --git a/examples/etc/otherfile b/vendor/gems/rspec/spec/spec/runner/resources/a_bar.rb
similarity index 100%
copy from examples/etc/otherfile
copy to vendor/gems/rspec/spec/spec/runner/resources/a_bar.rb
diff --git a/examples/etc/otherfile b/vendor/gems/rspec/spec/spec/runner/resources/a_foo.rb
similarity index 100%
rename from examples/etc/otherfile
rename to vendor/gems/rspec/spec/spec/runner/resources/a_foo.rb
diff --git a/vendor/gems/rspec/spec/spec/runner/resources/a_spec.rb b/vendor/gems/rspec/spec/spec/runner/resources/a_spec.rb
new file mode 100644
index 0000000..d9b67cc
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/resources/a_spec.rb
@@ -0,0 +1 @@
+# Empty - used by ../options_spec.rb
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/runner/spec.opts b/vendor/gems/rspec/spec/spec/runner/spec.opts
new file mode 100644
index 0000000..fd816a4
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/spec.opts
@@ -0,0 +1,2 @@
+--diff
+--colour
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/runner/spec_parser/spec_parser_fixture.rb b/vendor/gems/rspec/spec/spec/runner/spec_parser/spec_parser_fixture.rb
new file mode 100644
index 0000000..14602d9
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/spec_parser/spec_parser_fixture.rb
@@ -0,0 +1,70 @@
+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 SpecParserSubject, "described", :something => :something_else do
+
+   it "7" do
+   end
+
+end
+
+describe "described", :something => :something_else do
+
+  it "8" do
+  end
+
+end
+
+describe "e" do
+
+  it "9" do
+  end
+
+  it "10" do
+  end
+
+  describe "f" do
+    it "11" do
+    end
+
+    it "12" do
+    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 0000000..3d8d9c2
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/spec_parser_spec.rb
@@ -0,0 +1,79 @@
+require File.dirname(__FILE__) + '/../../spec_helper.rb'
+
+describe "SpecParser" do
+  attr_reader :parser, :file
+  before(:each) do
+    @parser = Spec::Runner::SpecParser.new
+    @file = "#{File.dirname(__FILE__)}/spec_parser/spec_parser_fixture.rb"
+    require file
+  end
+
+  it "should find spec name for 'specify' at same line" do
+    parser.spec_name_for(file, 5).should == "c 1"
+  end
+
+  it "should find spec name for 'specify' at end of spec line" do
+    parser.spec_name_for(file, 6).should == "c 1"
+  end
+
+  it "should find context for 'context' above all specs" do
+    parser.spec_name_for(file, 4).should == "c"
+  end
+
+  it "should find spec name for 'it' at same line" do
+    parser.spec_name_for(file, 15).should == "d 3"
+  end
+
+  it "should find spec name for 'it' at end of spec line" do
+    parser.spec_name_for(file, 16).should == "d 3"
+  end
+
+  it "should find context for 'describe' above all specs" do
+    parser.spec_name_for(file, 14).should == "d"
+  end
+
+ it "should find nearest example name between examples" do
+   parser.spec_name_for(file, 7).should == "c 1"
+ end
+
+  it "should find nothing outside a context" do
+    parser.spec_name_for(file, 2).should be_nil
+  end
+
+  it "should find context name for type" do
+    parser.spec_name_for(file, 26).should == "SpecParserSubject"
+  end
+
+  it "should find context and spec name for type" do
+    parser.spec_name_for(file, 28).should == "SpecParserSubject 5"
+  end
+
+  it "should find context and description for type" do
+    parser.spec_name_for(file, 33).should == "SpecParserSubject described"
+  end
+
+  it "should find context and description and example for type" do
+    parser.spec_name_for(file, 36).should == "SpecParserSubject described 6"
+  end
+
+  it "should find context and description for type with modifications" do
+    parser.spec_name_for(file, 40).should == "SpecParserSubject described"
+  end
+
+  it "should find context and described and example for type with modifications" do
+    parser.spec_name_for(file, 43).should == "SpecParserSubject described 7"
+  end
+
+  it "should find example group" do
+    parser.spec_name_for(file, 47).should == "described"
+  end
+
+  it "should find example" do
+    parser.spec_name_for(file, 50).should == "described 8"
+  end
+
+  it "should find nested example" do
+    parser.spec_name_for(file, 63).should == "e f 11"
+  end
+
+end
diff --git a/vendor/gems/rspec/spec/spec/runner/spec_spaced.opts b/vendor/gems/rspec/spec/spec/runner/spec_spaced.opts
new file mode 100644
index 0000000..6b3efd2
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner/spec_spaced.opts
@@ -0,0 +1,2 @@
+--diff --colour
+--format s
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/runner_spec.rb b/vendor/gems/rspec/spec/spec/runner_spec.rb
new file mode 100644
index 0000000..d75e661
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/runner_spec.rb
@@ -0,0 +1,11 @@
+require File.dirname(__FILE__) + '/../spec_helper.rb'
+
+module Spec
+  describe Runner, ".configure" do
+    it "should yield global configuration" do
+      Spec::Runner.configure do |config|
+        config.should equal(Spec::Runner.configuration)
+      end
+    end
+  end
+end
\ No newline at end of file
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 0000000..c8900a7
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/spec_classes.rb
@@ -0,0 +1,133 @@
+# 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
+        
+        def items
+          @items_in_collection_with_size_method
+        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
+  require 'spec/runner/formatter/base_text_formatter'
+  class Formatter < Spec::Runner::Formatter::BaseTextFormatter
+    attr_reader :options, :where
+    
+    def initialize(options, where)
+      @options = options
+      @where = where
+    end
+  end
+
+  class BadFormatter < Spec::Runner::Formatter::BaseTextFormatter
+    attr_reader :where
+    
+    def initialize(options, where)
+      bad_method
+    end
+  end
+
+  class Differ
+    attr_reader :options
+    def initialize(options)
+      @options = options
+    end
+
+    def diff_as_object(target, expected)
+      ""
+    end
+  end
+end
+
+class FakeReporter < Spec::Runner::Reporter
+end
diff --git a/vendor/gems/rspec/spec/spec/story/builders.rb b/vendor/gems/rspec/spec/spec/story/builders.rb
new file mode 100644
index 0000000..77d50d5
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/builders.rb
@@ -0,0 +1,46 @@
+module Spec
+  module Story
+    class StoryBuilder
+      def initialize
+        @title = 'a story'
+        @narrative = 'narrative'
+      end
+      
+      def title(value)
+        @title = value
+        self
+      end
+      
+      def narrative(value)
+        @narrative = value
+        self
+      end
+      
+      def to_story(&block)
+        block = lambda {} unless block_given?
+        Story.new @title, @narrative, &block
+      end
+    end
+    
+    class ScenarioBuilder
+      def initialize
+        @name = 'a scenario'
+        @story = StoryBuilder.new.to_story
+      end
+      
+      def name(value)
+        @name = value
+        self
+      end
+      
+      def story(value)
+        @story = value
+        self
+      end
+      
+      def to_scenario(&block)
+        Scenario.new @story, @name, &block
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/extensions/main_spec.rb b/vendor/gems/rspec/spec/spec/story/extensions/main_spec.rb
new file mode 100644
index 0000000..acdc341
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/extensions/main_spec.rb
@@ -0,0 +1,161 @@
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+module Spec
+  module Story
+    module Extensions
+      describe "the main object extended with Main", :shared => true do
+        before(:each) do
+          @main = Class.new do; include Main; end
+          @original_rspec_story_steps, $rspec_story_steps = $rspec_story_steps, nil
+        end
+
+        after(:each) do
+          $rspec_story_steps = @original_rspec_story_steps
+        end
+
+        def have_step(type, name)
+          return simple_matcher(%[step group containing a #{type} named #{name.inspect}]) do |actual|
+            Spec::Story::Step === actual.find(type, name)
+          end
+        end
+      end
+
+      describe Main, "#run_story" do
+        it_should_behave_like "the main object extended with Main"
+
+        it "should create a PlainTextStoryRunner with run_story" do
+          Spec::Story::Runner::PlainTextStoryRunner.should_receive(:new).and_return(mock("runner", :null_object => true))
+          @main.run_story
+        end
+
+        it "should yield the runner if arity == 1" do
+          File.should_receive(:read).with("some/path").and_return("Story: foo")
+          $main_spec_runner = nil
+          @main.run_story("some/path") do |runner|
+            $main_spec_runner = runner
+          end
+          $main_spec_runner.should be_an_instance_of(Spec::Story::Runner::PlainTextStoryRunner)
+        end
+
+        it "should run in the runner if arity == 0" do
+          File.should_receive(:read).with("some/path").and_return("Story: foo")
+          $main_spec_runner = nil
+          @main.run_story("some/path") do
+            $main_spec_runner = self
+          end
+          $main_spec_runner.should be_an_instance_of(Spec::Story::Runner::PlainTextStoryRunner)
+        end
+
+        it "should tell the PlainTextStoryRunner to run with run_story" do
+          runner = mock("runner")
+          Spec::Story::Runner::PlainTextStoryRunner.should_receive(:new).and_return(runner)
+          runner.should_receive(:run)
+          @main.run_story
+        end  
+      end
+
+      describe Main, "#steps_for" do
+        it_should_behave_like "the main object extended with Main"
+
+        it "should have no steps for a non existent key" do
+          @main.steps_for(:key).find(:given, "foo").should be_nil
+        end
+
+        it "should create steps for a key" do
+          $main_spec_invoked = false
+          @main.steps_for(:key) do
+            Given("foo") {
+              $main_spec_invoked = true
+            }
+          end
+          @main.steps_for(:key).find(:given, "foo").perform(Object.new, "foo")
+          $main_spec_invoked.should be_true
+        end
+
+        it "should append steps to steps_for a given key" do
+          @main.steps_for(:key) do
+            Given("first") {}
+          end
+          @main.steps_for(:key) do
+            Given("second") {}
+          end
+          @main.steps_for(:key).should have_step(:given, "first")
+          @main.steps_for(:key).should have_step(:given, "second")
+        end
+      end
+
+      describe Main, "#with_steps_for adding new steps" do
+        it_should_behave_like "the main object extended with Main"
+
+        it "should result in a group containing pre-existing steps and newly defined steps" do
+          first_group = @main.steps_for(:key) do
+            Given("first") {}
+          end
+          second_group = @main.with_steps_for(:key) do
+            Given("second") {}
+          end
+
+          second_group.should have_step(:given, "first")
+          second_group.should have_step(:given, "second")
+        end
+
+        it "should not add its steps to the existing group" do
+          first_group = @main.steps_for(:key) do
+            Given("first") {}
+          end
+          second_group = @main.with_steps_for(:key) do
+            Given("second") {}
+          end
+
+          first_group.should have_step(:given, "first")
+          first_group.should_not have_step(:given, "second")
+        end
+      end
+
+      describe Main, "#with_steps_for running a story" do
+        it_should_behave_like "the main object extended with Main"
+        
+        before(:each) do
+          @runner = mock("runner")
+          @runner_step_group = StepGroup.new
+          @runner.stub!(:steps).and_return(@runner_step_group)
+          @runner.stub!(:run)
+          Spec::Story::Runner::PlainTextStoryRunner.stub!(:new).and_return(@runner)
+        end
+        
+        it "should create a PlainTextStoryRunner with a path" do
+          Spec::Story::Runner::PlainTextStoryRunner.should_receive(:new).with('path/to/file',{}).and_return(@runner)
+          @main.with_steps_for(:foo) do
+            run 'path/to/file'
+          end
+        end
+        
+        it "should create a PlainTextStoryRunner with a path and options" do
+          Spec::Story::Runner::PlainTextStoryRunner.should_receive(:new).with(anything,{:bar => :baz}).and_return(@runner)
+          @main.with_steps_for(:foo) do
+            run 'path/to/file', :bar => :baz
+          end
+        end
+        
+        it "should pass the group it creates to the runner's steps" do
+          steps = @main.steps_for(:ice_cream) do
+            Given("vanilla") {}
+          end
+          @main.with_steps_for(:ice_cream) do
+            run 'foo'
+          end
+          @runner_step_group.should have_step(:given, "vanilla")
+        end
+        
+        it "should run a story" do
+          @runner.should_receive(:run)
+          Spec::Story::Runner::PlainTextStoryRunner.should_receive(:new).and_return(@runner)
+          @main.with_steps_for(:foo) do
+            run 'path/to/file'
+          end
+        end
+
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/story/extensions_spec.rb b/vendor/gems/rspec/spec/spec/story/extensions_spec.rb
new file mode 100644
index 0000000..612ddc7
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/extensions_spec.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+require 'spec/story'
+
+describe Kernel, "#Story" do
+  before(:each) do
+    Kernel.stub!(:at_exit)
+  end
+
+  it "should delegate to ::Spec::Story::Runner.story_runner" do
+    ::Spec::Story::Runner.story_runner.should_receive(:Story)
+    story = Story("title","narrative"){}
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/given_scenario_spec.rb b/vendor/gems/rspec/spec/spec/story/given_scenario_spec.rb
new file mode 100644
index 0000000..a688f88
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/given_scenario_spec.rb
@@ -0,0 +1,27 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+module Spec
+  module Story
+    describe GivenScenario do
+      it 'should execute a scenario from the current story in its world' do
+        # given
+        class MyWorld
+          attr :scenario_ran
+        end
+        instance = World.create(MyWorld)
+        scenario = ScenarioBuilder.new.to_scenario do
+          @scenario_ran = true
+        end
+        Runner::StoryRunner.should_receive(:scenario_from_current_story).with('scenario name').and_return(scenario)
+        
+        step = GivenScenario.new 'scenario name'
+        
+        # when
+        step.perform(instance, nil)
+        
+        # then
+        instance.scenario_ran.should be_true
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/runner/plain_text_story_runner_spec.rb b/vendor/gems/rspec/spec/spec/story/runner/plain_text_story_runner_spec.rb
new file mode 100644
index 0000000..1d5f2e0
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/runner/plain_text_story_runner_spec.rb
@@ -0,0 +1,92 @@
+require File.dirname(__FILE__) + '/../story_helper'
+
+module Spec
+  module Story
+    module Runner
+      describe PlainTextStoryRunner do
+        before(:each) do
+          StoryParser.stub!(:new).and_return(@parser = mock("parser"))
+          @parser.stub!(:parse).and_return([])
+          File.stub!(:read).with("path").and_return("this\nand that")
+        end
+
+        it "should provide access to steps" do
+          runner = PlainTextStoryRunner.new("path")
+          
+          runner.steps do |add|
+            add.given("baz") {}
+          end
+          
+          runner.steps.find(:given, "baz").should_not be_nil
+        end
+        
+        it "should parse a story file" do
+          runner = PlainTextStoryRunner.new("path")
+          
+          during {
+            runner.run
+          }.expect {
+            @parser.should_receive(:parse).with(["this", "and that"])
+          }
+        end
+        
+        it "should build up a mediator with its own steps and the singleton story_runner" do
+          runner = PlainTextStoryRunner.new("path")
+          Spec::Story::Runner.should_receive(:story_runner).and_return(story_runner = mock("story runner"))
+          Spec::Story::Runner::StoryMediator.should_receive(:new).with(runner.steps, story_runner, {}).
+            and_return(mediator = stub("mediator", :run_stories => nil))
+          runner.run
+        end
+        
+        it "should build up a parser with the mediator" do
+          runner = PlainTextStoryRunner.new("path")
+          Spec::Story::Runner.should_receive(:story_runner).and_return(story_runner = mock("story runner"))
+          Spec::Story::Runner::StoryMediator.should_receive(:new).and_return(mediator = stub("mediator", :run_stories => nil))
+          Spec::Story::Runner::StoryParser.should_receive(:new).with(mediator).and_return(@parser)
+          runner.run
+        end
+        
+        it "should tell the mediator to run the stories" do
+          runner = PlainTextStoryRunner.new("path")
+          mediator = mock("mediator")
+          Spec::Story::Runner::StoryMediator.should_receive(:new).and_return(mediator)
+          mediator.should_receive(:run_stories)
+          runner.run
+        end
+        
+        it "should accept a block instead of a path" do
+          runner = PlainTextStoryRunner.new do |runner|
+            runner.load("path/to/story")
+          end
+          File.should_receive(:read).with("path/to/story").and_return("this\nand that")
+          runner.run
+        end
+        
+        it "should tell you if you try to run with no path set" do
+          runner = PlainTextStoryRunner.new
+          lambda {
+            runner.run
+          }.should raise_error(RuntimeError, "You must set a path to the file with the story. See the RDoc.")
+        end
+        
+        it "should pass options to the mediator" do
+          runner = PlainTextStoryRunner.new("path", :foo => :bar)
+          Spec::Story::Runner::StoryMediator.should_receive(:new).
+            with(anything, anything, :foo => :bar).
+            and_return(mediator = stub("mediator", :run_stories => nil))
+          runner.run
+        end
+        
+        it "should provide access to its options" do
+          runner = PlainTextStoryRunner.new("path")
+          runner[:foo] = :bar
+          Spec::Story::Runner::StoryMediator.should_receive(:new).
+            with(anything, anything, :foo => :bar).
+            and_return(mediator = stub("mediator", :run_stories => nil))
+          runner.run
+        end
+        
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/story/runner/scenario_collector_spec.rb b/vendor/gems/rspec/spec/spec/story/runner/scenario_collector_spec.rb
new file mode 100644
index 0000000..042c41e
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/runner/scenario_collector_spec.rb
@@ -0,0 +1,27 @@
+require File.dirname(__FILE__) + '/../story_helper'
+
+module Spec
+  module Story
+    module Runner
+      describe ScenarioCollector do
+        it 'should construct scenarios with the supplied story' do
+          # given
+          story = stub_everything('story')
+          scenario_collector = ScenarioCollector.new(story)
+          
+          # when
+          scenario_collector.Scenario 'scenario1' do end
+          scenario_collector.Scenario 'scenario2' do end
+          scenarios = scenario_collector.scenarios
+          
+          # then
+          scenario_collector.should have(2).scenarios
+          scenarios.first.name.should == 'scenario1'
+          scenarios.first.story.should equal(story)
+          scenarios.last.name.should == 'scenario2'
+          scenarios.last.story.should equal(story)
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/runner/scenario_runner_spec.rb b/vendor/gems/rspec/spec/spec/story/runner/scenario_runner_spec.rb
new file mode 100644
index 0000000..a69ed4a
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/runner/scenario_runner_spec.rb
@@ -0,0 +1,142 @@
+require File.dirname(__FILE__) + '/../story_helper'
+
+module Spec
+  module Story
+    module Runner
+      describe ScenarioRunner do
+        it 'should run a scenario in its story' do
+          # given
+          world = stub_everything
+          scenario_runner = ScenarioRunner.new
+          $answer = nil
+          story = Story.new 'story', 'narrative' do
+            @answer = 42 # this should be available to the scenario
+          end
+          scenario = Scenario.new story, 'scenario' do
+            $answer = @answer
+          end
+          
+          # when
+          scenario_runner.run(scenario, world)
+          
+          # then
+          $answer.should == 42
+        end
+        
+        it 'should allow scenarios to share methods' do
+          # given
+          world = stub_everything
+          $shared_invoked = 0
+          story = Story.new 'story', 'narrative' do
+            def shared
+              $shared_invoked += 1
+            end
+          end
+          scenario1 = Scenario.new story, 'scenario1' do
+            shared()
+          end
+          scenario2 = Scenario.new story, 'scenario2' do
+            shared()
+          end
+          scenario_runner = ScenarioRunner.new
+          
+          # when
+          scenario_runner.run(scenario1, world)
+          scenario_runner.run(scenario2, world)
+          
+          # then
+          $shared_invoked.should == 2
+        end
+        
+        it 'should notify listeners when a scenario starts' do
+          # given
+          world = stub_everything
+          story = Story.new 'story', 'narrative' do end
+          scenario = Scenario.new story, 'scenario1' do
+            # succeeds
+          end
+          scenario_runner = ScenarioRunner.new
+          mock_listener1 = stub_everything('listener1')
+          mock_listener2 = stub_everything('listener2')
+          scenario_runner.add_listener(mock_listener1)
+          scenario_runner.add_listener(mock_listener2)
+          
+          # expect
+          mock_listener1.should_receive(:scenario_started).with('story', 'scenario1')
+          mock_listener2.should_receive(:scenario_started).with('story', 'scenario1')
+          
+          # when
+          scenario_runner.run(scenario, world)
+          
+          # then
+        end
+        
+        it 'should notify listeners when a scenario succeeds' do
+          # given
+          world = stub_everything('world')
+          story = Story.new 'story', 'narrative' do end
+          scenario = Scenario.new story, 'scenario1' do
+            # succeeds
+          end
+          scenario_runner = ScenarioRunner.new
+          mock_listener1 = stub_everything('listener1')
+          mock_listener2 = stub_everything('listener2')
+          scenario_runner.add_listener(mock_listener1)
+          scenario_runner.add_listener(mock_listener2)
+          
+          # expect
+          mock_listener1.should_receive(:scenario_succeeded).with('story', 'scenario1')
+          mock_listener2.should_receive(:scenario_succeeded).with('story', 'scenario1')
+          
+          # when
+          scenario_runner.run(scenario, world)
+          
+          # then
+        end
+        
+        it 'should notify listeners ONCE when a scenario raises an error' do
+          # given
+          error = RuntimeError.new('oops')
+          story = Story.new 'title', 'narrative' do end
+          scenario = Scenario.new story, 'scenario1' do
+          end
+          scenario_runner = ScenarioRunner.new
+          mock_listener = stub_everything('listener')
+          scenario_runner.add_listener(mock_listener)
+          world = stub_everything
+          
+          # expect
+          world.should_receive(:errors).twice.and_return([error, error])
+          mock_listener.should_receive(:scenario_failed).with('title', 'scenario1', error).once
+          
+          # when
+          scenario_runner.run scenario, world
+          
+          # then
+        end
+        
+        it 'should notify listeners when a scenario is pending' do
+          # given
+          pending_error = Spec::Example::ExamplePendingError.new('todo')
+          story = Story.new 'title', 'narrative' do end
+          scenario = Scenario.new story, 'scenario1' do
+          end
+          scenario_runner = ScenarioRunner.new
+          mock_listener = mock('listener')
+          scenario_runner.add_listener(mock_listener)
+          world = stub_everything
+          
+          # expect
+          world.should_receive(:errors).twice.and_return([pending_error, pending_error])
+          mock_listener.should_receive(:scenario_started).with('title', 'scenario1')
+          mock_listener.should_receive(:scenario_pending).with('title', 'scenario1', 'todo').once
+          
+          # when
+          scenario_runner.run scenario, world
+          
+          # then
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/runner/story_mediator_spec.rb b/vendor/gems/rspec/spec/spec/story/runner/story_mediator_spec.rb
new file mode 100644
index 0000000..4192e48
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/runner/story_mediator_spec.rb
@@ -0,0 +1,133 @@
+require File.dirname(__FILE__) + '/../story_helper'
+
+module Spec
+  module Story
+    module Runner
+      
+      describe StoryMediator do
+        before(:each) do
+          $story_mediator_spec_value = nil
+          @step_group = StepGroup.new
+          @step_group.create_matcher(:given, "given") { $story_mediator_spec_value = "given matched" }
+          @step_group.create_matcher(:when, "when") { $story_mediator_spec_value = "when matched" }
+          @step_group.create_matcher(:then, "then") { $story_mediator_spec_value = "then matched" }
+          
+          @scenario_runner = ScenarioRunner.new
+          @runner = StoryRunner.new @scenario_runner
+          @mediator = StoryMediator.new @step_group, @runner
+        end
+        
+        def run_stories
+          @mediator.run_stories
+          @runner.run_stories
+        end
+        
+        it "should have no stories" do
+          @mediator.stories.should be_empty
+        end
+        
+        it "should create two stories" do
+          @mediator.create_story "story title", "story narrative"
+          @mediator.create_story "story title 2", "story narrative 2"
+          run_stories
+          
+          @runner.should have(2).stories
+          @runner.stories.first.title.should == "story title"
+          @runner.stories.first.narrative.should == "story narrative"
+          @runner.stories.last.title.should == "story title 2"
+          @runner.stories.last.narrative.should == "story narrative 2"
+        end
+        
+        it "should create a scenario" do
+          @mediator.create_story "title", "narrative"
+          @mediator.create_scenario "scenario name"
+          run_stories
+          
+          @runner.should have(1).scenarios
+          @runner.scenarios.first.name.should == "scenario name"
+          @runner.scenarios.first.story.should == @runner.stories.first
+        end
+
+        it "should create a given scenario step if one matches" do
+          pending("need to untangle the dark mysteries of the story runner - something needs to get stubbed here") do
+            story = @mediator.create_story "title", "narrative"
+            @mediator.create_scenario "previous scenario"
+            @mediator.create_scenario "current scenario"
+            @mediator.create_given_scenario "previous scenario"
+            run_stories
+          
+            $story_mediator_spec_value.should == "previous scenario matched"
+          end
+        end
+                
+        it "should create a given step if one matches" do
+          @mediator.create_story "title", "narrative"
+          @mediator.create_scenario "scenario"
+          @mediator.create_given "given"
+          run_stories
+          
+          $story_mediator_spec_value.should == "given matched"
+        end
+        
+        it "should create a pending step if no given step matches" do
+          @mediator.create_story "title", "narrative"
+          @mediator.create_scenario "scenario"
+          @mediator.create_given "no match"
+          mock_listener = stub_everything("listener")
+          mock_listener.should_receive(:scenario_pending).with("title", "scenario", "Unimplemented step: no match")
+          @scenario_runner.add_listener mock_listener
+          run_stories
+        end
+        
+        it "should create a when step if one matches" do
+          @mediator.create_story "title", "narrative"
+          @mediator.create_scenario "scenario"
+          @mediator.create_when "when"
+          run_stories
+          
+          $story_mediator_spec_value.should == "when matched"
+        end
+        
+        it "should create a pending step if no when step matches" do
+          @mediator.create_story "title", "narrative"
+          @mediator.create_scenario "scenario"
+          @mediator.create_when "no match"
+          mock_listener = stub_everything("listener")
+          mock_listener.should_receive(:scenario_pending).with("title", "scenario", "Unimplemented step: no match")
+          @scenario_runner.add_listener mock_listener
+          run_stories
+        end
+        
+        it "should create a then step if one matches" do
+          @mediator.create_story "title", "narrative"
+          @mediator.create_scenario "scenario"
+          @mediator.create_then "then"
+          run_stories
+          
+          $story_mediator_spec_value.should == "then matched"
+        end
+        
+        it "should create a pending step if no 'then' step matches" do
+          @mediator.create_story "title", "narrative"
+          @mediator.create_scenario "scenario"
+          @mediator.create_then "no match"
+          mock_listener = stub_everything("listener")
+          mock_listener.should_receive(:scenario_pending).with("title", "scenario", "Unimplemented step: no match")
+          @scenario_runner.add_listener mock_listener
+          run_stories
+        end
+        
+        it "should pass options to the stories it creates" do
+          @mediator = StoryMediator.new @step_group, @runner, :foo => :bar
+          @mediator.create_story "story title", "story narrative"
+
+          run_stories
+          
+          @runner.stories.first[:foo].should == :bar
+        end
+        
+      end
+      
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/story/runner/story_parser_spec.rb b/vendor/gems/rspec/spec/spec/story/runner/story_parser_spec.rb
new file mode 100644
index 0000000..5efc8fd
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/runner/story_parser_spec.rb
@@ -0,0 +1,384 @@
+require File.dirname(__FILE__) + '/../story_helper'
+
+module Spec
+	module Story
+		module Runner
+		  
+			describe StoryParser do
+			  before(:each) do
+			    @story_mediator = mock("story_mediator")
+		    	@parser = StoryParser.new(@story_mediator)
+			  end
+
+			  it "should parse no lines" do
+					@parser.parse([])
+			  end
+			  
+			  it "should ignore text before the first Story: begins" do
+			    @story_mediator.should_not_receive(:create_scenario)
+			    @story_mediator.should_not_receive(:create_given)
+			    @story_mediator.should_not_receive(:create_when)
+			    @story_mediator.should_not_receive(:create_then)
+			    @story_mediator.should_receive(:create_story).with("simple addition", "")
+					@parser.parse(["Here is a bunch of text", "about a calculator and all the things", "that it will do", "Story: simple addition"])
+		    end
+			  
+			  it "should create a story" do
+			    @story_mediator.should_receive(:create_story).with("simple addition", "")
+					@parser.parse(["Story: simple addition"])
+			  end
+			  
+			  it "should create a story when line has leading spaces" do
+			    @story_mediator.should_receive(:create_story).with("simple addition", "")
+					@parser.parse(["    Story: simple addition"])
+			  end
+			  
+			  it "should add a one line narrative to the story" do
+			    @story_mediator.should_receive(:create_story).with("simple addition","narrative")
+					@parser.parse(["Story: simple addition","narrative"])
+			  end
+			  
+			  it "should add a multi line narrative to the story" do
+			    @story_mediator.should_receive(:create_story).with("simple addition","narrative line 1\nline 2\nline 3")
+					@parser.parse(["Story: simple addition","narrative line 1", "line 2", "line 3"])
+			  end
+			  
+			  it "should exclude blank lines from the narrative" do
+			    @story_mediator.should_receive(:create_story).with("simple addition","narrative line 1\nline 2")
+					@parser.parse(["Story: simple addition","narrative line 1", "", "line 2"])
+			  end
+			  
+			  it "should exclude Scenario from the narrative" do
+			    @story_mediator.should_receive(:create_story).with("simple addition","narrative line 1\nline 2")
+			    @story_mediator.should_receive(:create_scenario)
+					@parser.parse(["Story: simple addition","narrative line 1", "line 2", "Scenario: add one plus one"])
+			  end
+			  
+			end
+
+			describe StoryParser, "in Story state" do
+			  before(:each) do
+			    @story_mediator = mock("story_mediator")
+		    	@parser = StoryParser.new(@story_mediator)
+			    @story_mediator.stub!(:create_story)
+			  end
+			  
+			  it "should create a second Story for Story" do
+          @story_mediator.should_receive(:create_story).with("number two","")
+					@parser.parse(["Story: s", "Story: number two"])
+			  end
+			  
+			  it "should include And in the narrative" do
+          @story_mediator.should_receive(:create_story).with("s","And foo")
+          @story_mediator.should_receive(:create_scenario).with("bar")
+					@parser.parse(["Story: s", "And foo", "Scenario: bar"])
+			  end
+			  
+			  it "should create a Scenario for Scenario" do
+          @story_mediator.should_receive(:create_scenario).with("number two")
+					@parser.parse(["Story: s", "Scenario: number two"])
+			  end
+
+			  it "should include Given in the narrative" do
+          @story_mediator.should_receive(:create_story).with("s","Given foo")
+          @story_mediator.should_receive(:create_scenario).with("bar")
+					@parser.parse(["Story: s", "Given foo", "Scenario: bar"])
+			  end
+			  
+			  it "should include Given: in the narrative" do
+          @story_mediator.should_receive(:create_story).with("s","Given: foo")
+          @story_mediator.should_receive(:create_scenario).with("bar")
+					@parser.parse(["Story: s", "Given: foo", "Scenario: bar"])
+			  end
+			  			  
+			  it "should include When in the narrative" do
+          @story_mediator.should_receive(:create_story).with("s","When foo")
+          @story_mediator.should_receive(:create_scenario).with("bar")
+					@parser.parse(["Story: s", "When foo", "Scenario: bar"])
+			  end
+			  			  
+			  it "should include Then in the narrative" do
+          @story_mediator.should_receive(:create_story).with("s","Then foo")
+          @story_mediator.should_receive(:create_scenario).with("bar")
+					@parser.parse(["Story: s", "Then foo", "Scenario: bar"])
+			  end
+			  			  
+			  it "should include other in the story" do
+          @story_mediator.should_receive(:create_story).with("s","narrative")
+					@parser.parse(["Story: s", "narrative"])
+			  end
+			end
+			
+			describe StoryParser, "in Scenario state" do
+			  before(:each) do
+			    @story_mediator = mock("story_mediator")
+		    	@parser = StoryParser.new(@story_mediator)
+			    @story_mediator.stub!(:create_story)
+			    @story_mediator.stub!(:create_scenario)
+			  end
+			  
+			  it "should create a Story for Story" do
+          @story_mediator.should_receive(:create_story).with("number two","")
+					@parser.parse(["Story: s", "Scenario: s", "Story: number two"])
+			  end
+			  
+			  it "should create a Scenario for Scenario" do
+          @story_mediator.should_receive(:create_scenario).with("number two")
+					@parser.parse(["Story: s", "Scenario: s", "Scenario: number two"])
+			  end
+
+			  it "should raise for And" do
+			    lambda {
+  					@parser.parse(["Story: s", "Scenario: s", "And second"])
+			    }.should raise_error(IllegalStepError, /^Illegal attempt to create a And after a Scenario/)
+			  end
+			  
+			  it "should create a Given for Given" do
+          @story_mediator.should_receive(:create_given).with("gift")
+					@parser.parse(["Story: s", "Scenario: s", "Given gift"])
+			  end
+			  
+			  it "should create a Given for Given:" do
+          @story_mediator.should_receive(:create_given).with("gift")
+					@parser.parse(["Story: s", "Scenario: s", "Given: gift"])
+			  end
+			  
+			  it "should create a GivenScenario for GivenScenario" do
+          @story_mediator.should_receive(:create_given_scenario).with("previous")
+					@parser.parse(["Story: s", "Scenario: s", "GivenScenario previous"])
+			  end
+			  
+			  it "should create a GivenScenario for GivenScenario:" do
+          @story_mediator.should_receive(:create_given_scenario).with("previous")
+					@parser.parse(["Story: s", "Scenario: s", "GivenScenario: previous"])
+			  end
+			  
+			  it "should transition to Given state after GivenScenario" do
+          @story_mediator.stub!(:create_given_scenario)
+					@parser.parse(["Story: s", "Scenario: s", "GivenScenario previous"])
+					@parser.instance_eval{@state}.should be_an_instance_of(StoryParser::GivenState)
+			  end
+			  
+			  it "should transition to Given state after GivenScenario:" do
+          @story_mediator.stub!(:create_given_scenario)
+					@parser.parse(["Story: s", "Scenario: s", "GivenScenario: previous"])
+					@parser.instance_eval{@state}.should be_an_instance_of(StoryParser::GivenState)
+			  end
+			  
+			  it "should create a When for When" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "When ever"])
+			  end
+			  
+			  it "should create a When for When:" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "When: ever"])
+			  end
+			  
+			  it "should create a Then for Then" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Then and there"])
+			  end
+			  
+			  it "should create a Then for Then:" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Then: and there"])
+			  end
+			  
+			  it "should ignore other" do
+					@parser.parse(["Story: s", "Scenario: s", "this is ignored"])
+			  end
+			end
+						
+			describe StoryParser, "in Given state" do
+			  before(:each) do
+			    @story_mediator = mock("story_mediator")
+		    	@parser = StoryParser.new(@story_mediator)
+			    @story_mediator.stub!(:create_story)
+			    @story_mediator.stub!(:create_scenario)
+			    @story_mediator.should_receive(:create_given).with("first")
+			  end
+			  
+			  it "should create a Story for Story" do
+          @story_mediator.should_receive(:create_story).with("number two","")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "Story: number two"])
+			  end
+			  
+			  it "should create a Scenario for Scenario" do
+          @story_mediator.should_receive(:create_scenario).with("number two")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "Scenario: number two"])
+			  end
+
+			  it "should create a second Given for Given" do
+          @story_mediator.should_receive(:create_given).with("second")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "Given second"])
+			  end
+			  
+			  it "should create a second Given for And" do
+          @story_mediator.should_receive(:create_given).with("second")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "And second"])
+			  end
+			  
+			  it "should create a second Given for And:" do
+          @story_mediator.should_receive(:create_given).with("second")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "And: second"])
+			  end
+			  
+			  it "should create a When for When" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When ever"])
+			  end
+			  
+			  it "should create a When for When:" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When: ever"])
+			  end
+			  
+			  it "should create a Then for Then" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "Then and there"])
+			  end
+			  
+			  it "should create a Then for Then:" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "Then: and there"])
+			  end
+			  
+			  it "should ignore other" do
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "this is ignored"])
+			  end
+			end
+
+			describe StoryParser, "in When state" do
+			  before(:each) do
+			    @story_mediator = mock("story_mediator")
+		    	@parser = StoryParser.new(@story_mediator)
+			    @story_mediator.stub!(:create_story)
+			    @story_mediator.stub!(:create_scenario)
+			    @story_mediator.should_receive(:create_given).with("first")
+			    @story_mediator.should_receive(:create_when).with("else")
+			  end
+			  
+			  it "should create a Story for Story" do
+          @story_mediator.should_receive(:create_story).with("number two","")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When: else", "Story: number two"])
+			  end
+			  
+			  it "should create a Scenario for Scenario" do
+          @story_mediator.should_receive(:create_scenario).with("number two")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Scenario: number two"])
+			  end
+
+			  it "should create Given for Given" do
+          @story_mediator.should_receive(:create_given).with("second")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Given second"])
+			  end
+			  
+			  it "should create Given for Given:" do
+          @story_mediator.should_receive(:create_given).with("second")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Given: second"])
+			  end
+			  
+			  it "should create a second When for When" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "When ever"])
+			  end
+			  
+			  it "should create a second When for When:" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "When: else", "When: ever"])
+			  end
+			  
+			  it "should create a second When for And" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "And ever"])
+			  end
+			  
+			  it "should create a second When for And:" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "When: else", "And: ever"])
+			  end
+			  
+			  it "should create a Then for Then" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then and there"])
+			  end
+			  
+			  it "should create a Then for Then:" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "When: else", "Then: and there"])
+			  end
+			  
+			  it "should ignore other" do
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "this is ignored"])
+			  end
+			end
+
+			describe StoryParser, "in Then state" do
+			  before(:each) do
+			    @story_mediator = mock("story_mediator")
+		    	@parser = StoryParser.new(@story_mediator)
+			    @story_mediator.stub!(:create_story)
+			    @story_mediator.stub!(:create_scenario)
+			    @story_mediator.should_receive(:create_given).with("first")
+			    @story_mediator.should_receive(:create_when).with("else")
+			    @story_mediator.should_receive(:create_then).with("what")
+			  end
+			  
+			  it "should create a Story for Story" do
+          @story_mediator.should_receive(:create_story).with("number two","")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then what", "Story: number two"])
+			  end
+			  
+			  it "should create a Scenario for Scenario" do
+          @story_mediator.should_receive(:create_scenario).with("number two")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then what", "Scenario: number two"])
+			  end
+
+			  it "should create Given for Given" do
+          @story_mediator.should_receive(:create_given).with("second")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then what", "Given second"])
+			  end
+			  
+			  it "should create Given for Given:" do
+          @story_mediator.should_receive(:create_given).with("second")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "When: else", "Then: what", "Given: second"])
+			  end
+			  
+			  it "should create When for When" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then what", "When ever"])
+			  end
+			  
+			  it "should create When for When:" do
+          @story_mediator.should_receive(:create_when).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "When: else", "Then: what", "When: ever"])
+			  end
+
+			  it "should create a Then for Then" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then what", "Then and there"])
+			  end
+			  
+			  it "should create a Then for Then:" do
+          @story_mediator.should_receive(:create_then).with("and there")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "When: else", "Then: what", "Then: and there"])
+			  end
+
+			  it "should create a second Then for And" do
+          @story_mediator.should_receive(:create_then).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then what", "And ever"])
+			  end
+			  
+			  it "should create a second Then for And:" do
+          @story_mediator.should_receive(:create_then).with("ever")
+					@parser.parse(["Story: s", "Scenario: s", "Given: first", "When: else", "Then: what", "And: ever"])
+			  end
+
+			  it "should ignore other" do
+					@parser.parse(["Story: s", "Scenario: s", "Given first", "When else", "Then what", "this is ignored"])
+			  end
+			end
+		end
+	end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/spec/spec/story/runner/story_runner_spec.rb b/vendor/gems/rspec/spec/spec/story/runner/story_runner_spec.rb
new file mode 100644
index 0000000..0fc4640
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/runner/story_runner_spec.rb
@@ -0,0 +1,256 @@
+require File.dirname(__FILE__) + '/../story_helper'
+
+module Spec
+  module Story
+    module Runner
+      describe StoryRunner do
+        it 'should collect all the stories' do
+          # given
+          story_runner = StoryRunner.new(stub('scenario_runner'))
+          
+          # when
+          story_runner.Story 'title1', 'narrative1' do end
+          story_runner.Story 'title2', 'narrative2' do end
+          stories = story_runner.stories
+          
+          # then
+          story_runner.should have(2).stories
+          stories.first.title.should == 'title1'
+          stories.first.narrative.should == 'narrative1'
+          stories.last.title.should == 'title2'
+          stories.last.narrative.should == 'narrative2'
+        end
+        
+        it 'should gather all the scenarios in the stories' do
+          # given
+          story_runner = StoryRunner.new(stub('scenario_runner'))
+          
+          # when
+          story_runner.Story "story1", "narrative1" do
+            Scenario "scenario1" do end
+            Scenario "scenario2" do end
+          end
+          story_runner.Story "story2", "narrative2" do
+            Scenario "scenario3" do end
+          end
+          scenarios = story_runner.scenarios
+          
+          # then
+          story_runner.should have(3).scenarios
+          scenarios[0].name.should == 'scenario1'
+          scenarios[1].name.should == 'scenario2'
+          scenarios[2].name.should == 'scenario3'
+        end
+        
+        # captures worlds passed into a ScenarioRunner
+        class ScenarioWorldCatcher
+          attr_accessor :worlds
+          def run(scenario, world)
+           (@worlds ||= [])  << world
+          end
+        end
+        
+        it 'should run each scenario in a separate object' do
+          # given
+          scenario_world_catcher = ScenarioWorldCatcher.new
+          story_runner = StoryRunner.new(scenario_world_catcher)
+          story_runner.Story 'story', 'narrative' do
+            Scenario 'scenario1' do end
+            Scenario 'scenario2' do end
+          end
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+          worlds = scenario_world_catcher.worlds
+          scenario_world_catcher.should have(2).worlds
+          worlds[0].should_not == worlds[1]
+        end
+        
+        it 'should use the provided world creator to create worlds' do
+          # given
+          stub_scenario_runner = stub_everything
+          mock_world_creator = mock('world creator')
+          story_runner = StoryRunner.new(stub_scenario_runner, mock_world_creator)
+          story_runner.Story 'story', 'narrative' do
+            Scenario 'scenario1' do end
+            Scenario 'scenario2' do end
+          end
+          
+          # expect
+          mock_world_creator.should_receive(:create).twice
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+        end
+        
+        it 'should notify listeners of the scenario count when the run starts' do
+          # given
+          story_runner = StoryRunner.new(stub_everything)
+          mock_listener1 = stub_everything('listener1')
+          mock_listener2 = stub_everything('listener2')
+          story_runner.add_listener(mock_listener1)
+          story_runner.add_listener(mock_listener2)
+          
+          story_runner.Story 'story1', 'narrative1' do
+            Scenario 'scenario1' do end
+          end
+          story_runner.Story 'story2', 'narrative2' do
+            Scenario 'scenario2' do end
+            Scenario 'scenario3' do end
+          end
+          
+          # expect
+          mock_listener1.should_receive(:run_started).with(3)
+          mock_listener2.should_receive(:run_started).with(3)
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+        end
+        
+        it 'should notify listeners when a story starts' do
+          # given
+          story_runner = StoryRunner.new(stub_everything)
+          mock_listener1 = stub_everything('listener1')
+          mock_listener2 = stub_everything('listener2')
+          story_runner.add_listener(mock_listener1)
+          story_runner.add_listener(mock_listener2)
+          
+          story_runner.Story 'story1', 'narrative1' do
+            Scenario 'scenario1' do end
+          end
+          story_runner.Story 'story2', 'narrative2' do
+            Scenario 'scenario2' do end
+            Scenario 'scenario3' do end
+          end
+          
+          # expect
+          mock_listener1.should_receive(:story_started).with('story1', 'narrative1')
+          mock_listener1.should_receive(:story_ended).with('story1', 'narrative1')
+          mock_listener2.should_receive(:story_started).with('story2', 'narrative2')
+          mock_listener2.should_receive(:story_ended).with('story2', 'narrative2')
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+        end
+        
+        it 'should notify listeners when the run ends' do
+          # given
+          story_runner = StoryRunner.new(stub_everything)
+          mock_listener1 = stub_everything('listener1')
+          mock_listener2 = stub_everything('listener2')
+          story_runner.add_listener mock_listener1
+          story_runner.add_listener mock_listener2
+          story_runner.Story 'story1', 'narrative1' do
+            Scenario 'scenario1' do end
+          end
+          
+          # expect
+          mock_listener1.should_receive(:run_ended)
+          mock_listener2.should_receive(:run_ended)
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+        end
+        
+        it 'should run a story in an instance of a specified class' do
+          # given
+          scenario_world_catcher = ScenarioWorldCatcher.new
+          story_runner = StoryRunner.new(scenario_world_catcher)
+          story_runner.Story 'title', 'narrative', :type => String do
+            Scenario 'scenario' do end
+          end
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+          scenario_world_catcher.worlds[0].should be_kind_of(String)
+          scenario_world_catcher.worlds[0].should be_kind_of(World)
+        end
+        
+        it 'should pass initialization params through to the constructed instance' do
+          # given
+          scenario_world_catcher = ScenarioWorldCatcher.new
+          story_runner = StoryRunner.new(scenario_world_catcher)
+          story_runner.Story 'title', 'narrative', :type => Array, :args => [3]  do
+            Scenario 'scenario' do end
+          end
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+          scenario_world_catcher.worlds[0].should be_kind_of(Array)
+          scenario_world_catcher.worlds[0].size.should == 3
+        end
+        
+        it 'should find a scenario in the current story by name' do
+          # given
+          story_runner = StoryRunner.new(ScenarioRunner.new)
+          $scenario = nil
+          
+          story_runner.Story 'title', 'narrative' do
+            Scenario 'first scenario' do
+            end
+            Scenario 'second scenario' do
+              $scenario = StoryRunner.scenario_from_current_story 'first scenario'
+            end
+          end
+          
+          # when
+          story_runner.run_stories
+          
+          # then
+          $scenario.name.should == 'first scenario'
+        end
+        
+        it "should clean the steps between stories" do
+          #given
+          story_runner = StoryRunner.new(ScenarioRunner.new)
+          result = mock 'result'
+          
+          step1 = Step.new('step') do
+            result.one
+          end
+          steps1 = StepGroup.new
+          steps1.add :when, step1
+          
+          story_runner.Story 'title', 'narrative', :steps => steps1 do
+            Scenario 'first scenario' do
+              When 'step'
+            end
+          end
+          
+          step2 = Step.new('step') do
+            result.two
+          end
+          steps2 = StepGroup.new
+          steps2.add :when, step2
+          
+          story_runner.Story 'title2', 'narrative', :steps => steps2 do
+            Scenario 'second scenario' do
+              When 'step'
+            end
+          end
+          
+          #then
+          result.should_receive(:one)
+          result.should_receive(:two)
+          
+          #when
+          story_runner.run_stories
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/runner_spec.rb b/vendor/gems/rspec/spec/spec/story/runner_spec.rb
new file mode 100644
index 0000000..81e8526
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/runner_spec.rb
@@ -0,0 +1,106 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+module Spec
+  module Story
+    describe Runner, "module" do
+      def dev_null
+        io = StringIO.new
+        def io.write(str)
+          str.to_s.size
+        end
+        return io
+      end
+      
+      before :each do
+        Kernel.stub!(:at_exit)
+        @stdout, $stdout = $stdout, dev_null
+        @argv = Array.new(ARGV)
+        @runner_module = Runner.dup
+        @world_creator = World.dup
+        @runner_module.module_eval { @run_options = @story_runner = @scenario_runner = @world_creator = nil }
+      end
+      
+      after :each do
+        $stdout = @stdout
+        ARGV.replace @argv
+        @runner_module.module_eval { @run_options = @story_runner = @scenario_runner = @world_creator = nil }
+      end
+      
+      it 'should wire up a singleton StoryRunner' do
+        @runner_module.story_runner.should_not be_nil
+      end
+      
+      it 'should set its options based on ARGV' do
+        # given
+        ARGV << '--dry-run'
+        
+        # when
+        options = @runner_module.run_options
+        
+        # then
+        options.dry_run.should be_true
+      end
+
+      it 'should add a reporter to the runner classes' do
+        # given
+        story_runner = mock('story runner', :null_object => true)
+        scenario_runner = mock('scenario runner', :null_object => true)
+        world_creator = mock('world', :null_object => true)
+        
+        @runner_module::class_eval { @world_creator = world_creator }
+        @runner_module::StoryRunner.stub!(:new).and_return(story_runner)
+        @runner_module::ScenarioRunner.stub!(:new).and_return(scenario_runner)
+        
+        # expect
+        world_creator.should_receive(:add_listener).with(an_instance_of(Spec::Runner::Formatter::Story::PlainTextFormatter))
+        story_runner.should_receive(:add_listener).with(an_instance_of(Spec::Runner::Formatter::Story::PlainTextFormatter))
+        scenario_runner.should_receive(:add_listener).with(an_instance_of(Spec::Runner::Formatter::Story::PlainTextFormatter))
+        
+        # when
+        @runner_module.story_runner
+      end
+      
+      it 'should add a documenter to the runner classes if one is specified' do
+        # given
+        ARGV << "--format" << "html"
+        story_runner = mock('story runner', :null_object => true)
+        scenario_runner = mock('scenario runner', :null_object => true)
+        world_creator = mock('world', :null_object => true)
+        
+        @runner_module::class_eval { @world_creator = world_creator }
+        @runner_module::StoryRunner.stub!(:new).and_return(story_runner)
+        @runner_module::ScenarioRunner.stub!(:new).and_return(scenario_runner)
+        
+        # expect
+        world_creator.should_receive(:add_listener).with(an_instance_of(Spec::Runner::Formatter::Story::HtmlFormatter))
+        story_runner.should_receive(:add_listener).with(an_instance_of(Spec::Runner::Formatter::Story::HtmlFormatter))
+        scenario_runner.should_receive(:add_listener).with(an_instance_of(Spec::Runner::Formatter::Story::HtmlFormatter))
+        
+        # when
+        @runner_module.story_runner
+      end
+      
+      it 'should add any registered listener to the runner classes' do
+        # given
+        ARGV << "--format" << "html"
+        story_runner = mock('story runner', :null_object => true)
+        scenario_runner = mock('scenario runner', :null_object => true)
+        world_creator = mock('world', :null_object => true)
+        
+        @runner_module::class_eval { @world_creator = world_creator }
+        @runner_module::StoryRunner.stub!(:new).and_return(story_runner)
+        @runner_module::ScenarioRunner.stub!(:new).and_return(scenario_runner)
+        
+        listener = Object.new
+        
+        # expect
+        world_creator.should_receive(:add_listener).with(listener)
+        story_runner.should_receive(:add_listener).with(listener)
+        scenario_runner.should_receive(:add_listener).with(listener)
+        
+        # when
+        @runner_module.register_listener listener
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/scenario_spec.rb b/vendor/gems/rspec/spec/spec/story/scenario_spec.rb
new file mode 100644
index 0000000..0cf7aff
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/scenario_spec.rb
@@ -0,0 +1,20 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+module Spec
+  module Story
+    describe Scenario do
+      it 'should not raise an error if no body is supplied' do
+        # given
+        story = StoryBuilder.new.to_story
+        
+        # when
+        error = exception_from do
+          Scenario.new story, 'name'
+        end
+        
+        # then
+        error.should be_nil
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/step_group_spec.rb b/vendor/gems/rspec/spec/spec/story/step_group_spec.rb
new file mode 100644
index 0000000..dd28bfa
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/step_group_spec.rb
@@ -0,0 +1,157 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+module Spec
+  module Story
+    describe StepGroup do
+      before(:each) do
+        @step_group = StepGroup.new
+      end
+      
+      it "should not find a matcher if empty" do
+        @step_group.find(:given, "this and that").should be_nil
+      end
+      
+      it "should create a given_scenario matcher" do
+        step = @step_group.given_scenario("this and that") {}
+        @step_group.find(:given_scenario, "this and that").should_not be_nil
+        @step_group.find(:given_scenario, "this and that").should equal(step)
+      end
+      
+      it "should create a given matcher" do
+        step = @step_group.given("this and that") {}
+        @step_group.find(:given, "this and that").should equal(step)
+      end
+      
+      it "should create a when matcher" do
+        step = @step_group.when("this and that") {}
+        @step_group.find(:when, "this and that").should equal(step)
+      end
+      
+      it "should create a them matcher" do
+        step = @step_group.then("this and that") {}
+        @step_group.find(:then, "this and that").should equal(step)
+      end
+      
+      it "should add a matcher object" do
+        step = Step.new("this and that") {}
+        @step_group.add(:given, step)
+        @step_group.find(:given, "this and that").should equal(step)
+      end
+      
+      it "should add it matchers to another StepGroup (with one given)" do
+        source = StepGroup.new
+        target = StepGroup.new
+        step = source.given("this and that") {}
+        source.add_to target
+        target.find(:given, "this and that").should equal(step)
+      end
+      
+      it "should add it matchers to another StepGroup (with some of each type)" do
+        source = StepGroup.new
+        target = StepGroup.new
+        given_scenario = source.given_scenario("1") {}
+        given = source.given("1") {}
+        when1 = source.when("1") {}
+        when2 = source.when("2") {}
+        then1 = source.then("1") {}
+        then2 = source.then("2") {}
+        then3 = source.then("3") {}
+        source.add_to target
+        target.find(:given_scenario, "1").should equal(given_scenario)
+        target.find(:given, "1").should equal(given)
+        target.find(:when, "1").should equal(when1)
+        target.find(:when, "2").should equal(when2)
+        target.find(:then, "1").should equal(then1)
+        target.find(:then, "2").should equal(then2)
+        target.find(:then, "3").should equal(then3)
+      end
+      
+      it "should append another collection" do
+        matchers_to_append = StepGroup.new
+        step = matchers_to_append.given("this and that") {}
+        @step_group << matchers_to_append
+        @step_group.find(:given, "this and that").should equal(step)
+      end
+      
+      it "should append several other collections" do
+        matchers_to_append = StepGroup.new
+        more_matchers_to_append = StepGroup.new
+        first_matcher = matchers_to_append.given("this and that") {}
+        second_matcher = more_matchers_to_append.given("and the other") {}
+        @step_group << matchers_to_append
+        @step_group << more_matchers_to_append
+        @step_group.find(:given, "this and that").should equal(first_matcher)
+        @step_group.find(:given, "and the other").should equal(second_matcher)
+      end
+      
+      it "should yield itself on initialization" do
+        begin
+          $step_group_spec_step = nil
+          matchers = StepGroup.new do |matchers|
+            $step_group_spec_step = matchers.given("foo") {}
+          end
+          $step_group_spec_step.matches?("foo").should be_true
+        ensure
+          $step_group_spec_step = nil
+        end
+      end
+      
+      it "should support defaults" do
+        class StepGroupSubclass < StepGroup
+          steps do |add|
+            add.given("foo") {}
+          end
+        end
+        StepGroupSubclass.new.find(:given, "foo").should_not be_nil
+      end
+      
+      it "should create a Given" do
+        sub = Class.new(StepGroup).new
+        step = sub.Given("foo") {}
+        sub.find(:given, "foo").should == step
+      end
+      
+      it "should create a When" do
+        sub = Class.new(StepGroup).new
+        step = sub.When("foo") {}
+        sub.find(:when, "foo").should == step
+      end
+      
+      it "should create a Then" do
+        sub = Class.new(StepGroup).new
+        step = sub.Then("foo") {}
+        sub.find(:then, "foo").should == step
+      end
+      
+      it "should create steps in a block" do
+        sub = Class.new(StepGroup).new do
+          Given("a given") {}
+          When("a when") {}
+          Then("a then") {}
+        end
+        sub.find(:given, "a given").should_not be_nil
+        sub.find(:when, "a when").should_not be_nil
+        sub.find(:then, "a then").should_not be_nil
+      end
+      
+      it "should clear itself" do
+        step = @step_group.given("this and that") {}
+        @step_group.clear
+        @step_group.find(:given, "this and that").should be_nil
+      end
+      
+      it "should tell you when it is empty" do
+        @step_group.should be_empty
+      end
+      
+      it "should tell you when it is not empty" do
+        @step_group.given("this and that") {}
+        @step_group.should_not be_empty
+      end
+      
+      it "should handle << nil" do
+        @step_group << nil
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/step_mother_spec.rb b/vendor/gems/rspec/spec/spec/story/step_mother_spec.rb
new file mode 100644
index 0000000..64efd7a
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/step_mother_spec.rb
@@ -0,0 +1,72 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+module Spec
+  module Story
+    describe StepMother do
+      it 'should store a step by name and type' do
+        # given
+        step_mother = StepMother.new
+        step = Step.new("a given", &lambda {})
+        step_mother.store(:given, step)
+        
+        # when
+        found = step_mother.find(:given, "a given")
+        
+        # then
+        found.should == step
+      end
+      
+      it 'should NOT raise an error if a step is missing' do
+        # given
+        step_mother = StepMother.new
+        
+        # then
+        lambda do
+          # when
+          step_mother.find(:given, "doesn't exist")
+        end.should_not raise_error
+      end
+      
+      it "should create a default step which raises a pending error" do
+        # given
+        step_mother = StepMother.new
+        
+        # when
+        step = step_mother.find(:given, "doesn't exist")
+        
+        # then
+        step.should be_an_instance_of(Step)
+        
+        lambda do
+          step.perform(Object.new, "doesn't exist")
+        end.should raise_error(Spec::Example::ExamplePendingError, /Unimplemented/)
+      end
+      
+      it 'should clear itself' do
+        # given
+        step_mother = StepMother.new
+        step = Step.new("a given") do end
+        step_mother.store(:given, step)
+
+        # when
+        step_mother.clear
+        
+        # then
+        step_mother.should be_empty
+      end
+      
+      it "should use assigned steps" do
+        step_mother = StepMother.new
+        
+        step = Step.new('step') {}
+        step_group = StepGroup.new
+        step_group.add(:given, step)
+        
+        step_mother.use(step_group)
+                
+        step_mother.find(:given, "step").should equal(step)
+      end
+
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/step_spec.rb b/vendor/gems/rspec/spec/spec/story/step_spec.rb
new file mode 100644
index 0000000..0b6e515
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/step_spec.rb
@@ -0,0 +1,200 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+module Spec
+  module Story
+    describe Step, "matching" do
+      it "should match a text string" do
+        step = Step.new("this text") {}
+        step.matches?("this text").should be_true
+      end
+      
+      it "should not match a text string that does not start the same" do
+        step = Step.new("this text") {}
+        step.matches?("Xthis text").should be_false
+      end
+      
+      it "should not match a text string that does not end the same" do
+        step = Step.new("this text") {}
+        step.matches?("this textX").should be_false
+      end
+      
+      it "should match a text string with a param" do
+        step = Step.new("this $param text") {}
+        step.matches?("this anything text").should be_true
+      end
+      
+      it "should not be greedy" do
+        step = Step.new("enter $value for $key") {}
+        step.parse_args("enter 3 for keys for a piano").should == ['3','keys for a piano']
+      end
+      
+      it "should match a text string with 3 params" do
+        step = Step.new("1 $one 2 $two 3 $three 4") {}
+        step.matches?("1 a 2 b 3 c 4").should be_true
+      end
+      
+      it "should match a text string with a param at the beginning" do
+        step = Step.new("$one 2 3") {}
+        step.matches?("a 2 3").should be_true
+      end
+      
+      it "should match a text string with a param at the end" do
+        step = Step.new("1 2 $three") {}
+        step.matches?("1 2 c").should be_true
+      end
+      
+      it "should not match a different string" do
+        step = Step.new("this text") {}
+        step.matches?("other text").should be_false
+      end
+
+      it "should match a regexp" do
+        step = Step.new(/this text/) {}
+        step.matches?("this text").should be_true
+      end
+      
+      it "should match a regexp with a match group" do
+        step = Step.new(/this (.*) text/) {}
+        step.matches?("this anything text").should be_true
+      end
+      
+      it "should match a regexp with a named variable" do
+        step = Step.new(/this $variable text/) {}
+        step.matches?("this anything text").should be_true
+      end
+      
+      it "should not match a non matching regexp" do
+        step = Step.new(/this (.*) text/) {}
+        step.matches?("other anything text").should be_false
+      end
+      
+      it "should not match a non matching regexp with a named variable" do
+        step = Step.new(/this $variable text/) {}
+        step.matches?("other anything text").should be_false
+      end
+      
+      it "should not get bogged down by parens in strings" do
+        step = Step.new("before () after") {}
+        step.matches?("before () after").should be_true
+      end
+      
+      it "should match any option of an alteration" do
+        step = Step.new(/(he|she) is cool/) {}
+        step.matches?("he is cool").should be_true
+        step.matches?("she is cool").should be_true
+      end
+      
+      it "should match alteration as well as a variable" do
+        step = Step.new(/(he|she) is (.*)/) {}
+        step.matches?("he is cool").should be_true
+        step.parse_args("he is cool").should == ['he', 'cool']
+      end
+      
+      it "should match alteration as well as a named variable" do
+        step = Step.new(/(he|she) is $adjective/) {}
+        step.matches?("he is cool").should be_true
+        step.parse_args("he is cool").should == ['he', 'cool']
+      end
+      
+      it "should match alteration as well as a anonymous and named variable" do
+        step = Step.new(/(he|she) is (.*?) $adjective/) {}
+        step.matches?("he is very cool").should be_true
+        step.parse_args("he is very cool").should == ['he', 'very', 'cool']
+      end
+      
+    end
+    
+    describe Step do
+      it "should make complain with no block" do
+        lambda {
+          step = Step.new("foo")
+        }.should raise_error
+      end
+      
+      it "should perform itself on an object" do
+        # given
+        $instance = nil
+        step = Step.new 'step' do
+          $instance = self
+        end
+        instance = Object.new
+        
+        # when
+        step.perform(instance, "step")
+        
+        # then
+        $instance.should == instance
+      end
+      
+      it "should perform itself with one parameter with match expression" do
+        # given
+        $result = nil
+        step = Step.new 'an account with $count dollars' do |count|
+          $result = count
+        end
+        instance = Object.new
+        
+        # when
+        args = step.parse_args("an account with 3 dollars")
+        step.perform(instance, *args)
+        
+        # then
+        $result.should == "3"
+      end
+      
+      it "should perform itself with one parameter without a match expression" do
+        # given
+        $result = nil
+        step = Step.new 'an account with a balance of' do |amount|
+          $result = amount
+        end
+        instance = Object.new
+        
+        # when
+        step.perform(instance, 20)
+        
+        # then
+        $result.should == 20
+      end
+      
+      it "should perform itself with 2 parameters" do
+        # given
+        $account_type = nil
+        $amount = nil
+        step = Step.new 'a $account_type account with $amount dollars' do |account_type, amount|
+          $account_type = account_type
+          $amount = amount
+        end
+        instance = Object.new
+        
+        # when
+        args = step.parse_args("a savings account with 3 dollars")
+        step.perform(instance, *args)
+        
+        # then
+        $account_type.should == "savings"
+        $amount.should == "3"
+      end
+
+      it "should perform itself when defined with a regexp with 2 parameters" do
+        # given
+        $pronoun = nil
+        $adjective = nil
+        step = Step.new /(he|she) is (.*)/ do |pronoun, adjective|
+          $pronoun = pronoun
+          $adjective = adjective
+        end
+        instance = Object.new
+        
+        # when
+        args = step.parse_args("he is cool")
+        step.perform(instance, *args)
+        
+        # then
+        $pronoun.should == "he"
+        $adjective.should == "cool"
+      end
+
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/story_helper.rb b/vendor/gems/rspec/spec/spec/story/story_helper.rb
new file mode 100644
index 0000000..bb906f2
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/story_helper.rb
@@ -0,0 +1,2 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+require File.dirname(__FILE__) + '/builders'
diff --git a/vendor/gems/rspec/spec/spec/story/story_spec.rb b/vendor/gems/rspec/spec/spec/story/story_spec.rb
new file mode 100644
index 0000000..21257e9
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/story_spec.rb
@@ -0,0 +1,86 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+module Spec
+  module Story
+    describe Story do
+      it 'should run itself in a given object' do
+        # given
+        $instance = nil
+        story = Story.new 'title', 'narrative' do
+          $instance = self
+        end
+        object = Object.new
+        
+        # when
+        story.run_in(object)
+        
+        # then
+        $instance.should be(object)
+      end
+      
+      it 'should not raise an error if no block is supplied' do
+        # when
+        error = exception_from do
+          Story.new 'title', 'narrative'
+        end
+        
+        # then
+        error.should be_nil
+      end
+      
+      it "should raise when error raised running in another object" do
+        #given
+        story = Story.new 'title', 'narrative' do
+          raise "this is raised in the story"
+        end
+        object = Object.new
+        
+        # when/then
+        lambda do
+          story.run_in(object)
+        end.should raise_error
+      end
+      
+      it "should use the steps it is told to using a StepGroup" do
+        story = Story.new("title", "narrative", :steps => steps = StepGroup.new) do end
+        assignee = mock("assignee")
+        assignee.should_receive(:use).with(steps)
+        story.assign_steps_to(assignee)
+      end
+
+      it "should use the steps it is told to using a key" do
+        begin
+          orig_rspec_story_steps = $rspec_story_steps
+          $rspec_story_steps = StepGroupHash.new
+          $rspec_story_steps[:foo] = steps = Object.new
+        
+          story = Story.new("title", "narrative", :steps_for => :foo) do end
+          assignee = mock("assignee")
+        
+          assignee.should_receive(:use).with(steps)
+          story.assign_steps_to(assignee)
+        ensure
+          $rspec_story_steps = orig_rspec_story_steps
+        end
+      end
+      
+      it "should use the steps it is told to using multiple keys" do
+        begin
+          orig_rspec_story_steps = $rspec_story_steps
+          $rspec_story_steps = StepGroupHash.new
+          $rspec_story_steps[:foo] = foo_steps = Object.new
+          $rspec_story_steps[:bar] = bar_steps = Object.new
+        
+          story = Story.new("title", "narrative", :steps_for => [:foo, :bar]) do end
+          assignee = mock("assignee")
+        
+          assignee.should_receive(:use).with(foo_steps)
+          assignee.should_receive(:use).with(bar_steps)
+          story.assign_steps_to(assignee)
+        ensure
+          $rspec_story_steps = orig_rspec_story_steps
+        end
+      end
+    end
+  end
+end
diff --git a/vendor/gems/rspec/spec/spec/story/world_spec.rb b/vendor/gems/rspec/spec/spec/story/world_spec.rb
new file mode 100644
index 0000000..f5113dc
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/story/world_spec.rb
@@ -0,0 +1,423 @@
+require File.dirname(__FILE__) + '/story_helper'
+
+require 'spec/story'
+
+module Spec
+  module Story
+    describe World do
+      before :each do
+        World.listeners.clear
+      end
+
+      after :each do
+        World.listeners.clear
+        World.step_mother.clear
+      end
+
+      it 'should create an object that mixes in a World' do
+        # when
+        obj = World::create
+
+        # then
+        obj.should be_kind_of(World)
+      end
+
+      it 'should create a World from any object type' do
+        # when
+        obj = World::create String
+
+        # then
+        obj.should be_kind_of(String)
+        obj.should be_kind_of(World)
+      end
+
+      it 'should pass arguments to #new when creating an object of a specified type that mixes in a world' do
+        # given
+        Thing = Struct.new(:name, :age)
+
+        # when
+        obj = World::create Thing, "David", "I'm not telling"
+
+        # then
+        obj.should be_an_instance_of(Thing)
+        obj.name.should == "David"
+        obj.age.should == "I'm not telling"
+        obj.should be_kind_of(World)
+      end
+
+      def ensure_world_executes_step(&block)
+        # given
+        obj = World::create
+        $step_ran = false
+
+        # when
+        obj.instance_eval(&block)
+
+        # then
+        $step_ran.should be_true
+      end
+
+      it 'should execute a Given, When or Then step' do
+        ensure_world_executes_step do
+          Given 'a given' do
+            $step_ran = true
+          end
+        end
+
+        ensure_world_executes_step do
+          When 'an event' do
+            $step_ran = true
+          end
+        end
+
+        ensure_world_executes_step do
+          Then 'an outcome' do
+            $step_ran = true
+          end
+        end
+      end
+
+      it 'should interpret Given... And... as multiple givens' do
+        # given
+        world = World.create
+        $steps = []
+
+        # when
+        world.instance_eval do
+          Given 'step 1' do
+            $steps << 1
+          end
+          And 'step 2' do
+            $steps << 2
+          end
+        end
+
+        # then
+        $steps.should == [1,2]
+        World.step_mother.find(:given, 'step 1').should_not be_nil
+        World.step_mother.find(:given, 'step 2').should_not be_nil
+      end
+
+      it 'should interpret When... And... as multiple events' do
+        # given
+        world = World.create
+        $steps = []
+
+        # when
+        world.instance_eval do
+          When 'step 1' do
+            $steps << 1
+          end
+          And 'step 2' do
+            $steps << 2
+          end
+        end
+
+        # then
+        $steps.should == [1,2]
+        World.step_mother.find(:when, 'step 1').should_not be_nil
+        World.step_mother.find(:when, 'step 2').should_not be_nil
+      end
+
+      it 'should interpret Then... And... as multiple outcomes' do
+        # given
+        world = World.create
+        $steps = []
+
+        # when
+        world.instance_eval do
+          Then 'step 1' do
+            $steps << 1
+          end
+          And 'step 2' do
+            $steps << 2
+          end
+        end
+
+        # then
+        $steps.should == [1,2]
+        World.step_mother.find(:then, 'step 1').should_not be_nil
+        World.step_mother.find(:then, 'step 2').should_not be_nil
+      end
+
+      it 'should reuse a given across scenarios' do
+        # given
+        $num_invoked = 0
+        a_world = World::create
+        a_world.instance_eval do
+          Given 'a given' do
+            $num_invoked += 1
+          end
+        end
+        another_world = World::create
+
+        # when
+        another_world.instance_eval do
+          Given 'a given' # without a body
+        end
+
+        # then
+        $num_invoked.should == 2
+      end
+
+      it 'should reuse an event across scenarios' do
+        # given
+        $num_invoked = 0
+        a_world = World::create
+        a_world.instance_eval do
+          When 'an event' do
+            $num_invoked += 1
+          end
+        end
+
+        another_world = World::create
+
+        # when
+        another_world.instance_eval do
+          When 'an event' # without a body
+        end
+
+        # then
+        $num_invoked.should == 2
+      end
+
+      it 'should reuse an outcome across scenarios' do
+        # given
+        $num_invoked = 0
+        a_world = World::create
+        a_world.instance_eval do
+          Then 'an outcome' do
+            $num_invoked += 1
+          end
+        end
+
+        another_world = World::create
+
+        # when
+        another_world.instance_eval do
+          Then 'an outcome' # without a body
+        end
+
+        # then
+        $num_invoked.should == 2
+      end
+
+      it 'should preserve instance variables between steps within a scenario' do
+        # given
+        world = World::create
+        $first = nil
+        $second = nil
+
+        # when
+        world.instance_eval do
+          Given 'given' do
+            @first = 'first'
+          end
+          When 'event' do
+            @second = @first # from given
+          end
+          Then 'outcome' do
+            $first = @first # from given
+            $second = @second # from event
+          end
+        end
+
+        # then
+        $first.should == 'first'
+        $second.should == 'first'
+      end
+
+      it 'should invoke a reused step in the new object instance' do
+        # given
+        $instances = []
+        $debug = true
+        world1 = World.create
+        world1.instance_eval do
+          Given 'a given' do
+            $instances << self.__id__
+          end
+        end
+        world2 = World.create
+
+        # when
+        world2.instance_eval do
+          Given 'a given' # reused
+          Then 'an outcome' do
+            $instances << __id__
+          end
+        end
+        $debug = false
+        # then
+        $instances.should == [ world1.__id__, world2.__id__, world2.__id__ ]
+      end
+
+      def ensure_world_collects_error(expected_error, &block)
+        # given
+        world = World.create
+        # $error = nil
+
+        # when
+        world.start_collecting_errors
+        world.instance_eval(&block)
+
+        # then
+        world.should have(1).errors
+        world.errors[0].should be_kind_of(expected_error)
+      end
+
+      it 'should collect a failure from a Given step' do
+        ensure_world_collects_error RuntimeError do
+          Given 'a given' do
+            raise RuntimeError, "oops"
+          end
+        end
+      end
+
+      it 'should collect a failure from a When step' do
+        ensure_world_collects_error RuntimeError do
+          When 'an event' do
+            raise RuntimeError, "oops"
+          end
+        end
+      end
+
+      it 'should collect a failure from a Then step' do
+        ensure_world_collects_error RuntimeError do
+          Then 'an outcome' do
+            raise RuntimeError, "oops"
+          end
+        end
+      end
+
+      it 'should inform listeners when it runs a Given, When or Then step' do
+        # given
+        world = World.create
+        mock_listener1 = mock('listener1')
+        mock_listener2 = mock('listener2')
+        World.add_listener(mock_listener1)
+        World.add_listener(mock_listener2)
+
+        # expect
+        mock_listener1.should_receive(:step_upcoming).with(:given, 'a context')
+        mock_listener1.should_receive(:step_succeeded).with(:given, 'a context')
+        mock_listener1.should_receive(:step_upcoming).with(:when, 'an event')
+        mock_listener1.should_receive(:step_succeeded).with(:when, 'an event')
+        mock_listener1.should_receive(:step_upcoming).with(:then, 'an outcome')
+        mock_listener1.should_receive(:step_succeeded).with(:then, 'an outcome')
+
+        mock_listener2.should_receive(:step_upcoming).with(:given, 'a context')
+        mock_listener2.should_receive(:step_succeeded).with(:given, 'a context')
+        mock_listener2.should_receive(:step_upcoming).with(:when, 'an event')
+        mock_listener2.should_receive(:step_succeeded).with(:when, 'an event')
+        mock_listener2.should_receive(:step_upcoming).with(:then, 'an outcome')
+        mock_listener2.should_receive(:step_succeeded).with(:then, 'an outcome')
+
+        # when
+        world.instance_eval do
+          Given 'a context' do end
+          When 'an event' do end
+          Then 'an outcome' do end
+        end
+
+        # then
+      end
+
+      it 'should tell listeners but not execute the step in dry-run mode' do
+        # given
+        Runner.stub!(:dry_run).and_return(true)
+        mock_listener = mock('listener')
+        World.add_listener(mock_listener)
+        $step_invoked = false
+        world = World.create
+
+        # expect
+        mock_listener.should_receive(:step_upcoming).with(:given, 'a context')
+        mock_listener.should_receive(:step_succeeded).with(:given, 'a context')
+
+        # when
+        world.instance_eval do
+          Given 'a context' do
+            $step_invoked = true
+          end
+        end
+
+        # then
+        $step_invoked.should be(false)
+      end
+
+      it 'should suppress listeners while it runs a GivenScenario' do
+        # given
+        $scenario_ran = false
+
+        scenario = ScenarioBuilder.new.name('a scenario').to_scenario do
+          $scenario_ran = true
+          Given 'given' do end
+          When 'event' do end
+          Then 'outcome' do end
+        end
+
+        given_scenario = GivenScenario.new('a scenario')
+        Runner::StoryRunner.should_receive(:scenario_from_current_story).
+          with('a scenario').and_return(scenario)
+
+        world = World.create
+        listener = mock('listener')
+        World.add_listener(listener)
+
+        # expect
+        listener.should_receive(:found_scenario).with(:'given scenario', 'a scenario')
+        listener.should_receive(:step_succeeded).never.with(:given, 'given')
+        listener.should_receive(:step_succeeded).never.with(:when, 'event')
+        listener.should_receive(:step_succeeded).never.with(:then, 'outcome')
+
+        # when
+        world.GivenScenario 'a scenario'
+
+        # then
+        $scenario_ran.should be_true
+      end
+
+      it 'should interpret GivenScenario... And... as multiple givens' do
+        # given
+        world = World.create
+        $steps = []
+
+        scenario = ScenarioBuilder.new.name('a scenario').to_scenario do
+          $steps << 1
+        end
+        Runner::StoryRunner.should_receive(:scenario_from_current_story).
+          with('a scenario').and_return(scenario)
+
+        # when
+        world.instance_eval do
+          GivenScenario 'a scenario'
+          And 'step 2' do
+            $steps << 2
+          end
+        end
+
+        # then
+        $steps.should == [1,2]
+        World.step_mother.find(:given, 'step 2').should_not be_nil
+      end
+
+      it 'should provide rspec matchers' do
+        # given
+        world = World.create
+
+        # then
+        world.instance_eval do
+          'hello'.should match(/^hello$/)
+        end
+      end
+
+      it "should use assigned matchers" do
+        world = World.create
+
+        World.should_receive(:use).with(steps = Object.new)
+
+        World.use(steps)
+      end
+    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 0000000..01293d9
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec/translator_spec.rb
@@ -0,0 +1,265 @@
+require File.dirname(__FILE__) + '/../spec_helper.rb'
+require 'spec/translator'
+
+describe "Translator" do
+  before do
+    @t = Spec::Translator.new
+  end
+  
+  it "should translate files" do
+    from = File.dirname(__FILE__) + '/..'
+    to = "#{Dir.tmpdir}/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 0000000..1318176
--- /dev/null
+++ b/vendor/gems/rspec/spec/spec_helper.rb
@@ -0,0 +1,103 @@
+require 'stringio'
+
+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 'spec/story'
+spec_classes_path = File.expand_path("#{dir}/../spec/spec/spec_classes")
+require spec_classes_path unless $LOAD_PATH.include?(spec_classes_path)
+require File.dirname(__FILE__) + '/../lib/spec/expectations/differs/default'
+
+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
+    
+    class CorrectlyOrderedMockExpectation
+      def initialize(&event)
+        @event = event
+      end
+      
+      def expect(&expectations)
+        expectations.call
+        @event.call
+      end
+    end
+    
+    def during(&block)
+      CorrectlyOrderedMockExpectation.new(&block) 
+    end
+  end
+end
+
+class NonStandardError < Exception; end
+
+module Custom
+  class ExampleGroupRunner
+    attr_reader :options, :arg
+    def initialize(options, arg)
+      @options, @arg = options, arg
+    end
+
+    def load_files(files)
+    end
+
+    def run
+    end
+  end  
+end
+
+def exception_from(&block)
+  exception = nil
+  begin
+    yield
+  rescue StandardError => e
+    exception = e
+  end
+  exception
+end
+
+describe "sandboxed rspec_options", :shared => true do
+  attr_reader :options
+
+  before(:all) do
+    @original_rspec_options = $rspec_options
+  end
+
+  before(:each) do
+    @options = ::Spec::Runner::Options.new(StringIO.new, StringIO.new)
+    $rspec_options = options
+  end
+
+  after do
+    $rspec_options = @original_rspec_options
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/stories/all.rb b/vendor/gems/rspec/stories/all.rb
new file mode 100644
index 0000000..c2428fd
--- /dev/null
+++ b/vendor/gems/rspec/stories/all.rb
@@ -0,0 +1,5 @@
+require File.join(File.dirname(__FILE__), *%w[helper])
+
+["example_groups","interop"].each do |dir|
+  require File.join(File.dirname(__FILE__), "#{dir}/stories")
+end
diff --git a/vendor/gems/rspec/stories/example_groups/autogenerated_docstrings b/vendor/gems/rspec/stories/example_groups/autogenerated_docstrings
new file mode 100644
index 0000000..b3ff689
--- /dev/null
+++ b/vendor/gems/rspec/stories/example_groups/autogenerated_docstrings
@@ -0,0 +1,45 @@
+Story: autogenerated docstrings
+
+  As an RSpec user
+  I want examples to generate their own names
+  So that I can reduce duplication between example names and example code
+
+  Scenario: run passing examples with ruby
+    Given the file ../../examples/pure/autogenerated_docstrings_example.rb
+
+    When I run it with the ruby interpreter -fs
+
+    Then the stdout should match /should equal 5/
+    And the stdout should match /should be < 5/
+    And the stdout should match /should include "a"/
+    And the stdout should match /should respond to #size/
+
+  Scenario: run failing examples with ruby
+    Given the file ../../failing_examples/failing_autogenerated_docstrings_example.rb
+
+    When I run it with the ruby interpreter -fs
+
+    Then the stdout should match /should equal 2/
+    And the stdout should match /should be > 5/
+    And the stdout should match /should include "b"/
+    And the stdout should match /should not respond to #size/
+
+  Scenario: run passing examples with spec
+    Given the file ../../examples/pure/autogenerated_docstrings_example.rb
+
+    When I run it with the spec script -fs
+
+    Then the stdout should match /should equal 5/
+    And the stdout should match /should be < 5/
+    And the stdout should match /should include "a"/
+    And the stdout should match /should respond to #size/
+
+  Scenario: run failing examples with spec
+    Given the file ../../failing_examples/failing_autogenerated_docstrings_example.rb
+
+    When I run it with the spec script -fs
+
+    Then the stdout should match /should equal 2/
+    And the stdout should match /should be > 5/
+    And the stdout should match /should include "b"/
+    And the stdout should match /should not respond to #size/
diff --git a/vendor/gems/rspec/stories/example_groups/example_group_with_should_methods b/vendor/gems/rspec/stories/example_groups/example_group_with_should_methods
new file mode 100644
index 0000000..3d2bc61
--- /dev/null
+++ b/vendor/gems/rspec/stories/example_groups/example_group_with_should_methods
@@ -0,0 +1,17 @@
+Story: Spec::ExampleGroup with should methods
+
+  As an RSpec adopter accustomed to classes and methods
+  I want to use should_* methods in an ExampleGroup
+  So that I use RSpec with classes and methods that look more like RSpec examples
+
+  Scenario: Run with ruby
+    Given the file spec/example_group_with_should_methods.rb
+    When I run it with the ruby interpreter
+    Then the exit code should be 256
+    And the stdout should match "2 examples, 1 failure"
+
+  Scenario: Run with spec
+  Given the file spec/example_group_with_should_methods.rb
+    When I run it with the spec script
+    Then the exit code should be 256
+    And the stdout should match "2 examples, 1 failure"
diff --git a/vendor/gems/rspec/stories/example_groups/nested_groups b/vendor/gems/rspec/stories/example_groups/nested_groups
new file mode 100644
index 0000000..ede9785
--- /dev/null
+++ b/vendor/gems/rspec/stories/example_groups/nested_groups
@@ -0,0 +1,17 @@
+Story: Nested example groups
+
+  As an RSpec user
+  I want to nest examples groups
+  So that I can better organize my examples
+
+  Scenario: Run with ruby
+    Given the file ../../examples/pure/stack_spec_with_nested_example_groups.rb
+    When I run it with the ruby interpreter -fs
+    Then the stdout should match /Stack \(empty\)/
+    And the stdout should match /Stack \(full\)/
+
+  Scenario: Run with ruby
+    Given the file ../../examples/pure/stack_spec_with_nested_example_groups.rb
+    When I run it with the spec script -fs
+    Then the stdout should match /Stack \(empty\)/
+    And the stdout should match /Stack \(full\)/
diff --git a/vendor/gems/rspec/stories/example_groups/output b/vendor/gems/rspec/stories/example_groups/output
new file mode 100644
index 0000000..4947bdc
--- /dev/null
+++ b/vendor/gems/rspec/stories/example_groups/output
@@ -0,0 +1,25 @@
+Story: Getting correct output
+
+  As an RSpec user
+  I want to see output only once
+  So that I don't get confused
+
+  Scenario: Run with ruby
+    Given the file spec/simple_spec.rb
+    When I run it with the ruby interpreter
+    Then the exit code should be 0
+    And the stdout should not match /\d+ tests, \d+ assertions, \d+ failures, \d+ errors/m
+    And the stdout should match "1 example, 0 failures"
+
+  Scenario: Run with CommandLine object
+    Given the file spec/simple_spec.rb
+    When I run it with the CommandLine object
+    Then the exit code should be 0
+    And the stdout should not match "Loaded suite"
+    And the stdout should not match /\d+ tests, \d+ assertions, \d+ failures, \d+ errors/m
+    And the stdout should match "1 example, 0 failures"
+
+  Scenario: Tweak backtrace
+    Given the file stories/failing_story.rb
+    When I run it with the ruby interpreter
+    Then the stdout should not match /\/lib\/spec\//
diff --git a/vendor/gems/rspec/stories/example_groups/stories.rb b/vendor/gems/rspec/stories/example_groups/stories.rb
new file mode 100644
index 0000000..e45882a
--- /dev/null
+++ b/vendor/gems/rspec/stories/example_groups/stories.rb
@@ -0,0 +1,7 @@
+require File.join(File.dirname(__FILE__), *%w[.. helper])
+
+with_steps_for :running_rspec do
+  Dir["#{File.dirname(__FILE__)}/*"].each do |file|
+    run file if File.file?(file) && !(file =~ /\.rb$/)
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/stories/helper.rb b/vendor/gems/rspec/stories/helper.rb
new file mode 100644
index 0000000..d9a105e
--- /dev/null
+++ b/vendor/gems/rspec/stories/helper.rb
@@ -0,0 +1,6 @@
+$LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/../lib")
+require 'spec'
+require 'tempfile'
+require File.join(File.dirname(__FILE__), *%w[resources matchers smart_match])
+require File.join(File.dirname(__FILE__), *%w[resources helpers story_helper])
+require File.join(File.dirname(__FILE__), *%w[resources steps running_rspec])
diff --git a/vendor/gems/rspec/stories/interop/examples_and_tests_together b/vendor/gems/rspec/stories/interop/examples_and_tests_together
new file mode 100644
index 0000000..6583f89
--- /dev/null
+++ b/vendor/gems/rspec/stories/interop/examples_and_tests_together
@@ -0,0 +1,30 @@
+Story: Spec and test together
+
+  As an RSpec adopter with existing Test::Unit tests
+  I want to run a few specs alongside my existing Test::Unit tests
+  So that I can experience a smooth, gradual migration path
+
+  Scenario: Run with ruby
+    Given the file test/spec_and_test_together.rb
+
+    When I run it with the ruby interpreter -fs
+
+    Then the exit code should be 256
+    And the stdout should match "ATest"
+    And the stdout should match "Test::Unit::AssertionFailedError in 'An Example should fail with assert'"
+    And the stdout should match "'An Example should fail with should' FAILED"
+    And the stdout should match "10 examples, 6 failures"
+    And the stdout should match /expected: 40,\s*got: 4/m
+    And the stdout should match /expected: 50,\s*got: 5/m
+  Scenario: Run with spec
+    Given the file test/spec_and_test_together.rb
+
+    When I run it with the spec script -fs
+
+    Then the exit code should be 256
+    Ands the stdout should match "ATest"
+    And the stdout should match "Test::Unit::AssertionFailedError in 'An Example should fail with assert'"
+    And the stdout should match "'An Example should fail with should' FAILED"
+    And the stdout should match "10 examples, 6 failures"
+    And the stdout should match /expected: 40,\s*got: 4/m
+    And the stdout should match /expected: 50,\s*got: 5/m
diff --git a/vendor/gems/rspec/stories/interop/stories.rb b/vendor/gems/rspec/stories/interop/stories.rb
new file mode 100644
index 0000000..e45882a
--- /dev/null
+++ b/vendor/gems/rspec/stories/interop/stories.rb
@@ -0,0 +1,7 @@
+require File.join(File.dirname(__FILE__), *%w[.. helper])
+
+with_steps_for :running_rspec do
+  Dir["#{File.dirname(__FILE__)}/*"].each do |file|
+    run file if File.file?(file) && !(file =~ /\.rb$/)
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/stories/interop/test_case_with_should_methods b/vendor/gems/rspec/stories/interop/test_case_with_should_methods
new file mode 100644
index 0000000..d618c50
--- /dev/null
+++ b/vendor/gems/rspec/stories/interop/test_case_with_should_methods
@@ -0,0 +1,17 @@
+Story: Test::Unit::TestCase extended by rspec with should methods
+
+  As an RSpec adopter with existing Test::Unit tests
+  I want to use should_* methods in a Test::Unit::TestCase
+  So that I use RSpec with classes and methods that look more like RSpec examples
+
+  Scenario: Run with ruby
+    Given the file test/test_case_with_should_methods.rb
+    When I run it with the ruby interpreter
+    Then the exit code should be 256
+    And the stdout should match "5 examples, 3 failures"
+
+  Scenario: Run with spec
+    Given the file test/test_case_with_should_methods.rb
+    When I run it with the spec script
+    Then the exit code should be 256
+    And the stdout should match "5 examples, 3 failures"
diff --git a/vendor/gems/rspec/stories/pending_stories/README b/vendor/gems/rspec/stories/pending_stories/README
new file mode 100644
index 0000000..2f9b443
--- /dev/null
+++ b/vendor/gems/rspec/stories/pending_stories/README
@@ -0,0 +1,3 @@
+This directory contains stories that are currently not passing
+because they are new or they represent regressions.
+
diff --git a/vendor/gems/rspec/stories/resources/helpers/cmdline.rb b/vendor/gems/rspec/stories/resources/helpers/cmdline.rb
new file mode 100644
index 0000000..ab86bd3
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/helpers/cmdline.rb
@@ -0,0 +1,9 @@
+$:.push File.join(File.dirname(__FILE__), *%w[.. .. .. lib])
+require 'spec'
+
+# Uncommenting next line will break the output story (no output!!)
+# rspec_options
+options = Spec::Runner::OptionParser.parse(
+  ARGV, $stderr, $stdout
+)
+Spec::Runner::CommandLine.run(options)
diff --git a/vendor/gems/rspec/stories/resources/helpers/story_helper.rb b/vendor/gems/rspec/stories/resources/helpers/story_helper.rb
new file mode 100644
index 0000000..e0aef5b
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/helpers/story_helper.rb
@@ -0,0 +1,16 @@
+require 'spec/story'
+require File.dirname(__FILE__) + '/../../../spec/ruby_forker'
+
+module StoryHelper
+  include RubyForker
+
+  def spec(args, stderr)
+    ruby("#{File.dirname(__FILE__) + '/../../../bin/spec'} #{args}", stderr)
+  end
+
+  def cmdline(args, stderr)
+    ruby("#{File.dirname(__FILE__) + '/../../resources/helpers/cmdline.rb'} #{args}", stderr)
+  end
+  
+  Spec::Story::World.send :include, self
+end
diff --git a/vendor/gems/rspec/stories/resources/matchers/smart_match.rb b/vendor/gems/rspec/stories/resources/matchers/smart_match.rb
new file mode 100644
index 0000000..7b1672b
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/matchers/smart_match.rb
@@ -0,0 +1,37 @@
+module Spec
+  module Matchers
+    class SmartMatch
+      def initialize(expected)
+        @expected = expected
+      end
+
+      def matches?(actual)
+        @actual = actual
+        # Satisfy expectation here. Return false or raise an error if it's not met.
+
+        if @expected =~ /^\/.*\/?$/ || @expected =~ /^".*"$/
+          regex_or_string = eval(@expected)
+          if Regexp === regex_or_string
+            (@actual =~ regex_or_string) ? true : false
+          else
+            @actual.index(regex_or_string) != nil
+          end
+        else
+          false
+        end
+      end
+
+      def failure_message
+        "expected #{@actual.inspect} to smart_match #{@expected.inspect}, but it didn't"
+      end
+
+      def negative_failure_message
+        "expected #{@actual.inspect} not to smart_match #{@expected.inspect}, but it did"
+      end
+    end
+
+    def smart_match(expected)
+      SmartMatch.new(expected)
+    end
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/stories/resources/spec/example_group_with_should_methods.rb b/vendor/gems/rspec/stories/resources/spec/example_group_with_should_methods.rb
new file mode 100644
index 0000000..4c0505d
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/spec/example_group_with_should_methods.rb
@@ -0,0 +1,12 @@
+$:.push File.join(File.dirname(__FILE__), *%w[.. .. .. lib])
+require 'spec'
+
+class MySpec < Spec::ExampleGroup
+  def should_pass_with_should
+    1.should == 1
+  end
+
+  def should_fail_with_should
+    1.should == 2
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/stories/resources/spec/simple_spec.rb b/vendor/gems/rspec/stories/resources/spec/simple_spec.rb
new file mode 100644
index 0000000..2fb67ba
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/spec/simple_spec.rb
@@ -0,0 +1,8 @@
+$:.push File.join(File.dirname(__FILE__), *%w[.. .. .. lib])
+require 'spec'
+
+describe "Running an Example" do
+  it "should not output twice" do
+    true.should be_true
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/stories/resources/steps/running_rspec.rb b/vendor/gems/rspec/stories/resources/steps/running_rspec.rb
new file mode 100644
index 0000000..496847f
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/steps/running_rspec.rb
@@ -0,0 +1,50 @@
+steps_for :running_rspec do
+
+  Given("the file $relative_path") do |relative_path|
+    @path = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "resources", relative_path))
+    unless File.exist?(@path)
+      raise "could not find file at #{@path}"
+    end
+  end
+  
+  When("I run it with the $interpreter") do |interpreter|
+    stderr_file = Tempfile.new('rspec')
+    stderr_file.close
+    @stdout = case(interpreter)
+      when /^ruby interpreter/
+        args = interpreter.gsub('ruby interpreter','')
+        ruby("#{@path}#{args}", stderr_file.path)
+      when /^spec script/
+        args = interpreter.gsub('spec script','')
+        spec("#{@path}#{args}", stderr_file.path)
+      when 'CommandLine object' then cmdline(@path, stderr_file.path)
+      else raise "Unknown interpreter: #{interpreter}"
+    end
+    @stderr = IO.read(stderr_file.path)
+    @exit_code = $?.to_i
+  end
+  
+  Then("the exit code should be $exit_code") do |exit_code|
+    if @exit_code != exit_code.to_i
+      raise "Did not exit with #{exit_code}, but with #{@exit_code}. Standard error:\n#{@stderr}"
+    end
+  end
+  
+  Then("the $stream should match $regex") do |stream, string_or_regex|
+    written = case(stream)
+      when 'stdout' then @stdout
+      when 'stderr' then @stderr
+      else raise "Unknown stream: #{stream}"
+    end
+    written.should smart_match(string_or_regex)
+  end
+  
+  Then("the $stream should not match $regex") do |stream, string_or_regex|
+    written = case(stream)
+      when 'stdout' then @stdout
+      when 'stderr' then @stderr
+      else raise "Unknown stream: #{stream}"
+    end
+    written.should_not smart_match(string_or_regex)
+  end
+end
diff --git a/vendor/gems/rspec/stories/resources/stories/failing_story.rb b/vendor/gems/rspec/stories/resources/stories/failing_story.rb
new file mode 100644
index 0000000..cc9506c
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/stories/failing_story.rb
@@ -0,0 +1,15 @@
+$:.push File.join(File.dirname(__FILE__), *%w[.. .. .. lib])
+
+require 'spec/story'
+
+Story "Failing story",
+%(As an RSpec user
+  I want a failing test
+  So that I can observe the output) do
+
+  Scenario "Failing scenario" do
+    Then "true should be false" do
+      true.should == false
+    end
+  end
+end
diff --git a/vendor/gems/rspec/stories/resources/test/spec_and_test_together.rb b/vendor/gems/rspec/stories/resources/test/spec_and_test_together.rb
new file mode 100644
index 0000000..eb2b4e0
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/test/spec_and_test_together.rb
@@ -0,0 +1,57 @@
+$:.push File.join(File.dirname(__FILE__), *%w[.. .. .. lib])
+require 'spec'
+# TODO - this should not be necessary, ay?
+require 'spec/interop/test'
+
+describe "An Example" do
+  it "should pass with assert" do
+    assert true
+  end
+
+  it "should fail with assert" do
+    assert false
+  end
+
+  it "should pass with should" do
+    1.should == 1
+  end
+
+  it "should fail with should" do
+    1.should == 2
+  end
+end
+
+class ATest < Test::Unit::TestCase
+  def test_should_pass_with_assert
+    assert true
+  end
+  
+  def test_should_fail_with_assert
+    assert false
+  end
+
+  def test_should_pass_with_should
+    1.should == 1
+  end
+  
+  def test_should_fail_with_should
+    1.should == 2
+  end
+
+  def setup
+    @from_setup ||= 3
+    @from_setup += 1
+  end
+
+  def test_should_fail_with_setup_method_variable
+    @from_setup.should == 40
+  end
+
+  before do
+    @from_before = @from_setup + 1
+  end
+
+  def test_should_fail_with_before_block_variable
+    @from_before.should == 50
+  end
+end
\ No newline at end of file
diff --git a/vendor/gems/rspec/stories/resources/test/test_case_with_should_methods.rb b/vendor/gems/rspec/stories/resources/test/test_case_with_should_methods.rb
new file mode 100644
index 0000000..3912429
--- /dev/null
+++ b/vendor/gems/rspec/stories/resources/test/test_case_with_should_methods.rb
@@ -0,0 +1,30 @@
+$:.push File.join(File.dirname(__FILE__), *%w[.. .. .. lib])
+require 'test/unit'
+require 'spec'
+require 'spec/interop/test'
+
+class MySpec < Test::Unit::TestCase
+  def should_pass_with_should
+    1.should == 1
+  end
+
+  def should_fail_with_should
+    1.should == 2
+  end
+
+  def should_pass_with_assert
+    assert true
+  end
+  
+  def should_fail_with_assert
+    assert false
+  end
+
+  def test
+    raise "This is not a real test"
+  end
+
+  def test_ify
+    raise "This is a real test"
+  end
+end
\ No newline at end of file

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list