diff options
Diffstat (limited to 'jni/ruby/test/lib/minitest')
| -rw-r--r-- | jni/ruby/test/lib/minitest/README.txt | 457 | ||||
| -rw-r--r-- | jni/ruby/test/lib/minitest/autorun.rb | 13 | ||||
| -rw-r--r-- | jni/ruby/test/lib/minitest/benchmark.rb | 417 | ||||
| -rw-r--r-- | jni/ruby/test/lib/minitest/mock.rb | 195 | ||||
| -rw-r--r-- | jni/ruby/test/lib/minitest/unit.rb | 1419 | 
5 files changed, 2501 insertions, 0 deletions
| diff --git a/jni/ruby/test/lib/minitest/README.txt b/jni/ruby/test/lib/minitest/README.txt new file mode 100644 index 0000000..368cc3a --- /dev/null +++ b/jni/ruby/test/lib/minitest/README.txt @@ -0,0 +1,457 @@ += minitest/{unit,spec,mock,benchmark} + +home :: https://github.com/seattlerb/minitest +rdoc :: http://docs.seattlerb.org/minitest +vim  :: https://github.com/sunaku/vim-ruby-minitest + +== DESCRIPTION: + +minitest provides a complete suite of testing facilities supporting +TDD, BDD, mocking, and benchmarking. + +    "I had a class with Jim Weirich on testing last week and we were +     allowed to choose our testing frameworks. Kirk Haines and I were +     paired up and we cracked open the code for a few test +     frameworks... + +     I MUST say that minitest is *very* readable / understandable +     compared to the 'other two' options we looked at. Nicely done and +     thank you for helping us keep our mental sanity." + +    -- Wayne E. Seguin + +minitest/unit is a small and incredibly fast unit testing framework. +It provides a rich set of assertions to make your tests clean and +readable. + +minitest/spec is a functionally complete spec engine. It hooks onto +minitest/unit and seamlessly bridges test assertions over to spec +expectations. + +minitest/benchmark is an awesome way to assert the performance of your +algorithms in a repeatable manner. Now you can assert that your newb +co-worker doesn't replace your linear algorithm with an exponential +one! + +minitest/mock by Steven Baker, is a beautifully tiny mock (and stub) +object framework. + +minitest/pride shows pride in testing and adds coloring to your test +output. I guess it is an example of how to write IO pipes too. :P + +minitest/unit is meant to have a clean implementation for language +implementors that need a minimal set of methods to bootstrap a working +test suite. For example, there is no magic involved for test-case +discovery. + +    "Again, I can't praise enough the idea of a testing/specing +     framework that I can actually read in full in one sitting!" + +    -- Piotr Szotkowski + +Comparing to rspec: + +    rspec is a testing DSL. minitest is ruby. + +    -- Adam Hawkins, "Bow Before MiniTest" + +minitest doesn't reinvent anything that ruby already provides, like: +classes, modules, inheritance, methods. This means you only have to +learn ruby to use minitest and all of your regular OO practices like +extract-method refactorings still apply. + +== FEATURES/PROBLEMS: + +* minitest/autorun - the easy and explicit way to run all your tests. +* minitest/unit - a very fast, simple, and clean test system. +* minitest/spec - a very fast, simple, and clean spec system. +* minitest/mock - a simple and clean mock/stub system. +* minitest/benchmark - an awesome way to assert your algorithm's performance. +* minitest/pride - show your pride in testing! +* Incredibly small and fast runner, but no bells and whistles. + +== RATIONALE: + +See design_rationale.rb to see how specs and tests work in minitest. + +== SYNOPSIS: + +Given that you'd like to test the following class: + +  class Meme +    def i_can_has_cheezburger? +      "OHAI!" +    end + +    def will_it_blend? +      "YES!" +    end +  end + +=== Unit tests + +  require 'minitest/autorun' + +  class TestMeme < MiniTest::Unit::TestCase +    def setup +      @meme = Meme.new +    end + +    def test_that_kitty_can_eat +      assert_equal "OHAI!", @meme.i_can_has_cheezburger? +    end + +    def test_that_it_will_not_blend +      refute_match /^no/i, @meme.will_it_blend? +    end + +    def test_that_will_be_skipped +      skip "test this later" +    end +  end + +=== Specs + +  require 'minitest/autorun' + +  describe Meme do +    before do +      @meme = Meme.new +    end + +    describe "when asked about cheeseburgers" do +      it "must respond positively" do +        @meme.i_can_has_cheezburger?.must_equal "OHAI!" +      end +    end + +    describe "when asked about blending possibilities" do +      it "won't say no" do +        @meme.will_it_blend?.wont_match /^no/i +      end +    end +  end + +For matchers support check out: + +https://github.com/zenspider/minitest-matchers + +=== Benchmarks + +Add benchmarks to your regular unit tests. If the unit tests fail, the +benchmarks won't run. + +  # optionally run benchmarks, good for CI-only work! +  require 'minitest/benchmark' if ENV["BENCH"] + +  class TestMeme < MiniTest::Unit::TestCase +    # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000] +    def bench_my_algorithm +      assert_performance_linear 0.9999 do |n| # n is a range value +        @obj.my_algorithm(n) +      end +    end +  end + +Or add them to your specs. If you make benchmarks optional, you'll +need to wrap your benchmarks in a conditional since the methods won't +be defined. + +  describe Meme do +    if ENV["BENCH"] then +      bench_performance_linear "my_algorithm", 0.9999 do |n| +        100.times do +          @obj.my_algorithm(n) +        end +      end +    end +  end + +outputs something like: + +  # Running benchmarks: + +  TestBlah	100	1000	10000 +  bench_my_algorithm	 0.006167	 0.079279	 0.786993 +  bench_other_algorithm	 0.061679	 0.792797	 7.869932 + +Output is tab-delimited to make it easy to paste into a spreadsheet. + +=== Mocks + +  class MemeAsker +    def initialize(meme) +      @meme = meme +    end + +    def ask(question) +      method = question.tr(" ","_") + "?" +      @meme.__send__(method) +    end +  end + +  require 'minitest/autorun' + +  describe MemeAsker do +    before do +      @meme = MiniTest::Mock.new +      @meme_asker = MemeAsker.new @meme +    end + +    describe "#ask" do +      describe "when passed an unpunctuated question" do +        it "should invoke the appropriate predicate method on the meme" do +          @meme.expect :will_it_blend?, :return_value +          @meme_asker.ask "will it blend" +          @meme.verify +        end +      end +    end +  end + +=== Stubs + +  def test_stale_eh +    obj_under_test = Something.new + +    refute obj_under_test.stale? + +    Time.stub :now, Time.at(0) do   # stub goes away once the block is done +      assert obj_under_test.stale? +    end +  end + +A note on stubbing: In order to stub a method, the method must +actually exist prior to stubbing. Use a singleton method to create a +new non-existing method: + +  def obj_under_test.fake_method +    ... +  end + +=== Customizable Test Runner Types: + +MiniTest::Unit.runner=(runner) provides an easy way of creating custom +test runners for specialized needs. Justin Weiss provides the +following real-world example to create an alternative to regular +fixture loading: + +  class MiniTestWithHooks::Unit < MiniTest::Unit +    def before_suites +    end + +    def after_suites +    end + +    def _run_suites(suites, type) +      begin +        before_suites +        super(suites, type) +      ensure +        after_suites +      end +    end + +    def _run_suite(suite, type) +      begin +        suite.before_suite +        super(suite, type) +      ensure +        suite.after_suite +      end +    end +  end + +  module MiniTestWithTransactions +    class Unit < MiniTestWithHooks::Unit +      include TestSetupHelper + +      def before_suites +        super +        setup_nested_transactions +        # load any data we want available for all tests +      end + +      def after_suites +        teardown_nested_transactions +        super +      end +    end +  end + +  MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new + +== FAQ + +=== How to test SimpleDelegates? + +The following implementation and test: + +    class Worker < SimpleDelegator +      def work +      end +    end + +    describe Worker do +      before do +        @worker = Worker.new(Object.new) +      end + +      it "must respond to work" do +        @worker.must_respond_to :work +      end +    end + +outputs a failure: + +      1) Failure: +    Worker#test_0001_must respond to work [bug11.rb:16]: +    Expected #<Object:0x007f9e7184f0a0> (Object) to respond to #work. + +Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject. +Expectations are put on Object (one level down) so the Worker +(SimpleDelegate) hits `method_missing` and delegates down to the +`Object.new` instance. That object doesn't respond to work so the test +fails. + +You can bypass `SimpleDelegate#method_missing` by extending the worker +with `MiniTest::Expectations`. You can either do that in your setup at +the instance level, like: + +    before do +      @worker = Worker.new(Object.new) +      @worker.extend MiniTest::Expectations +    end + +or you can extend the Worker class (within the test file!), like: + +    class Worker +      include ::MiniTest::Expectations +    end + +== Known Extensions: + +capybara_minitest_spec      :: Bridge between Capybara RSpec matchers and MiniTest::Spec expectations (e.g. page.must_have_content('Title')). +minispec-metadata           :: Metadata for describe/it blocks +                               (e.g. `it 'requires JS driver', js: true do`) +minitest-ansi               :: Colorize minitest output with ANSI colors. +minitest-around             :: Around block for minitest. An alternative to setup/teardown dance. +minitest-capistrano         :: Assertions and expectations for testing Capistrano recipes +minitest-capybara           :: Capybara matchers support for minitest unit and spec +minitest-chef-handler       :: Run Minitest suites as Chef report handlers +minitest-ci                 :: CI reporter plugin for MiniTest. +minitest-colorize           :: Colorize MiniTest output and show failing tests instantly. +minitest-context            :: Defines contexts for code reuse in MiniTest +                               specs that share common expectations. +minitest-debugger           :: Wraps assert so failed assertions drop into +                               the ruby debugger. +minitest-display            :: Patches MiniTest to allow for an easily configurable output. +minitest-emoji              :: Print out emoji for your test passes, fails, and skips. +minitest-english            :: Semantically symmetric aliases for assertions and expectations. +minitest-excludes           :: Clean API for excluding certain tests you +                               don't want to run under certain conditions. +minitest-firemock           :: Makes your MiniTest mocks more resilient. +minitest-great_expectations :: Generally useful additions to minitest's assertions and expectations +minitest-growl              :: Test notifier for minitest via growl. +minitest-implicit-subject   :: Implicit declaration of the test subject. +minitest-instrument         :: Instrument ActiveSupport::Notifications when +                               test method is executed +minitest-instrument-db      :: Store information about speed of test +                               execution provided by minitest-instrument in database +minitest-libnotify          :: Test notifier for minitest via libnotify. +minitest-macruby            :: Provides extensions to minitest for macruby UI testing. +minitest-matchers           :: Adds support for RSpec-style matchers to minitest. +minitest-metadata           :: Annotate tests with metadata (key-value). +minitest-mongoid            :: Mongoid assertion matchers for MiniTest +minitest-must_not           :: Provides must_not as an alias for wont in MiniTest +minitest-nc                 :: Test notifier for minitest via Mountain Lion's Notification Center +minitest-predicates         :: Adds support for .predicate? methods +minitest-rails              :: MiniTest integration for Rails 3.x +minitest-rails-capybara     :: Capybara integration for MiniTest::Rails +minitest-reporters          :: Create customizable MiniTest output formats +minitest-should_syntax      :: RSpec-style +x.should == y+ assertions for MiniTest +minitest-shouldify          :: Adding all manner of shoulds to MiniTest (bad idea) +minitest-spec-context       :: Provides rspec-ish context method to MiniTest::Spec +minitest-spec-magic         :: Minitest::Spec extensions for Rails and beyond +minitest-spec-rails         :: Drop in MiniTest::Spec superclass for ActiveSupport::TestCase. +minitest-stub-const         :: Stub constants for the duration of a block +minitest-tags               :: add tags for minitest +minitest-wscolor            :: Yet another test colorizer. +minitest_owrapper           :: Get tests results as a TestResult object. +minitest_should             :: Shoulda style syntax for minitest test::unit. +minitest_tu_shim            :: minitest_tu_shim bridges between test/unit and minitest. +mongoid-minitest            :: MiniTest matchers for Mongoid. +pry-rescue                  :: A pry plugin w/ minitest support. See pry-rescue/minitest.rb. + +== Unknown Extensions: + +Authors... Please send me a pull request with a description of your minitest extension. + +* assay-minitest +* detroit-minitest +* em-minitest-spec +* flexmock-minitest +* guard-minitest +* guard-minitest-decisiv +* minitest-activemodel +* minitest-ar-assertions +* minitest-capybara-unit +* minitest-colorer +* minitest-deluxe +* minitest-extra-assertions +* minitest-rails-shoulda +* minitest-spec +* minitest-spec-should +* minitest-sugar +* minitest_should +* mongoid-minitest +* spork-minitest + +== REQUIREMENTS: + +* Ruby 1.8, maybe even 1.6 or lower. No magic is involved. + +== INSTALL: + +  sudo gem install minitest + +On 1.9, you already have it. To get newer candy you can still install +the gem, but you'll need to activate the gem explicitly to use it: + +  require 'rubygems' +  gem 'minitest' # ensures you're using the gem, and not the built in MT +  require 'minitest/autorun' + +  # ... usual testing stuffs ... + +DO NOTE: There is a serious problem with the way that ruby 1.9/2.0 +packages their own gems. They install a gem specification file, but +don't install the gem contents in the gem path. This messes up +Gem.find_files and many other things (gem which, gem contents, etc). + +Just install minitest as a gem for real and you'll be happier. + +== LICENSE: + +(The MIT License) + +Copyright (c) Ryan Davis, seattle.rb + +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/jni/ruby/test/lib/minitest/autorun.rb b/jni/ruby/test/lib/minitest/autorun.rb new file mode 100644 index 0000000..88b1e05 --- /dev/null +++ b/jni/ruby/test/lib/minitest/autorun.rb @@ -0,0 +1,13 @@ +# encoding: utf-8 + +begin +  require 'rubygems' +  gem 'minitest' +rescue Gem::LoadError +  # do nothing +end + +require 'minitest/unit' +require 'minitest/mock' + +MiniTest::Unit.autorun diff --git a/jni/ruby/test/lib/minitest/benchmark.rb b/jni/ruby/test/lib/minitest/benchmark.rb new file mode 100644 index 0000000..5195fc0 --- /dev/null +++ b/jni/ruby/test/lib/minitest/benchmark.rb @@ -0,0 +1,417 @@ +# encoding: utf-8 + +require 'minitest/unit' + +class MiniTest::Unit # :nodoc: +  def run_benchmarks # :nodoc: +    _run_anything :benchmark +  end + +  def benchmark_suite_header suite # :nodoc: +    "\n#{suite}\t#{suite.bench_range.join("\t")}" +  end + +  class TestCase +    ## +    # Returns a set of ranges stepped exponentially from +min+ to +    # +max+ by powers of +base+. Eg: +    # +    #   bench_exp(2, 16, 2) # => [2, 4, 8, 16] + +    def self.bench_exp min, max, base = 10 +      min = (Math.log10(min) / Math.log10(base)).to_i +      max = (Math.log10(max) / Math.log10(base)).to_i + +      (min..max).map { |m| base ** m }.to_a +    end + +    ## +    # Returns a set of ranges stepped linearly from +min+ to +max+ by +    # +step+. Eg: +    # +    #   bench_linear(20, 40, 10) # => [20, 30, 40] + +    def self.bench_linear min, max, step = 10 +      (min..max).step(step).to_a +    rescue LocalJumpError # 1.8.6 +      r = []; (min..max).step(step) { |n| r << n }; r +    end + +    ## +    # Returns the benchmark methods (methods that start with bench_) +    # for that class. + +    def self.benchmark_methods # :nodoc: +      public_instance_methods(true).grep(/^bench_/).map { |m| m.to_s }.sort +    end + +    ## +    # Returns all test suites that have benchmark methods. + +    def self.benchmark_suites +      TestCase.test_suites.reject { |s| s.benchmark_methods.empty? } +    end + +    ## +    # Specifies the ranges used for benchmarking for that class. +    # Defaults to exponential growth from 1 to 10k by powers of 10. +    # Override if you need different ranges for your benchmarks. +    # +    # See also: ::bench_exp and ::bench_linear. + +    def self.bench_range +      bench_exp 1, 10_000 +    end + +    ## +    # Runs the given +work+, gathering the times of each run. Range +    # and times are then passed to a given +validation+ proc. Outputs +    # the benchmark name and times in tab-separated format, making it +    # easy to paste into a spreadsheet for graphing or further +    # analysis. +    # +    # Ranges are specified by ::bench_range. +    # +    # Eg: +    # +    #   def bench_algorithm +    #     validation = proc { |x, y| ... } +    #     assert_performance validation do |n| +    #       @obj.algorithm(n) +    #     end +    #   end + +    def assert_performance validation, &work +      range = self.class.bench_range + +      io.print "#{__name__}" + +      times = [] + +      range.each do |x| +        GC.start +        t0 = Time.now +        instance_exec(x, &work) +        t = Time.now - t0 + +        io.print "\t%9.6f" % t +        times << t +      end +      io.puts + +      validation[range, times] +    end + +    ## +    # Runs the given +work+ and asserts that the times gathered fit to +    # match a constant rate (eg, linear slope == 0) within a given +    # +threshold+. Note: because we're testing for a slope of 0, R^2 +    # is not a good determining factor for the fit, so the threshold +    # is applied against the slope itself. As such, you probably want +    # to tighten it from the default. +    # +    # See http://www.graphpad.com/curvefit/goodness_of_fit.htm for +    # more details. +    # +    # Fit is calculated by #fit_linear. +    # +    # Ranges are specified by ::bench_range. +    # +    # Eg: +    # +    #   def bench_algorithm +    #     assert_performance_constant 0.9999 do |n| +    #       @obj.algorithm(n) +    #     end +    #   end + +    def assert_performance_constant threshold = 0.99, &work +      validation = proc do |range, times| +        a, b, rr = fit_linear range, times +        assert_in_delta 0, b, 1 - threshold +        [a, b, rr] +      end + +      assert_performance validation, &work +    end + +    ## +    # Runs the given +work+ and asserts that the times gathered fit to +    # match a exponential curve within a given error +threshold+. +    # +    # Fit is calculated by #fit_exponential. +    # +    # Ranges are specified by ::bench_range. +    # +    # Eg: +    # +    #   def bench_algorithm +    #     assert_performance_exponential 0.9999 do |n| +    #       @obj.algorithm(n) +    #     end +    #   end + +    def assert_performance_exponential threshold = 0.99, &work +      assert_performance validation_for_fit(:exponential, threshold), &work +    end + +    ## +    # Runs the given +work+ and asserts that the times gathered fit to +    # match a logarithmic curve within a given error +threshold+. +    # +    # Fit is calculated by #fit_logarithmic. +    # +    # Ranges are specified by ::bench_range. +    # +    # Eg: +    # +    #   def bench_algorithm +    #     assert_performance_logarithmic 0.9999 do |n| +    #       @obj.algorithm(n) +    #     end +    #   end + +    def assert_performance_logarithmic threshold = 0.99, &work +      assert_performance validation_for_fit(:logarithmic, threshold), &work +    end + +    ## +    # Runs the given +work+ and asserts that the times gathered fit to +    # match a straight line within a given error +threshold+. +    # +    # Fit is calculated by #fit_linear. +    # +    # Ranges are specified by ::bench_range. +    # +    # Eg: +    # +    #   def bench_algorithm +    #     assert_performance_linear 0.9999 do |n| +    #       @obj.algorithm(n) +    #     end +    #   end + +    def assert_performance_linear threshold = 0.99, &work +      assert_performance validation_for_fit(:linear, threshold), &work +    end + +    ## +    # Runs the given +work+ and asserts that the times gathered curve +    # fit to match a power curve within a given error +threshold+. +    # +    # Fit is calculated by #fit_power. +    # +    # Ranges are specified by ::bench_range. +    # +    # Eg: +    # +    #   def bench_algorithm +    #     assert_performance_power 0.9999 do |x| +    #       @obj.algorithm +    #     end +    #   end + +    def assert_performance_power threshold = 0.99, &work +      assert_performance validation_for_fit(:power, threshold), &work +    end + +    ## +    # Takes an array of x/y pairs and calculates the general R^2 value. +    # +    # See: http://en.wikipedia.org/wiki/Coefficient_of_determination + +    def fit_error xys +      y_bar  = sigma(xys) { |x, y| y } / xys.size.to_f +      ss_tot = sigma(xys) { |x, y| (y    - y_bar) ** 2 } +      ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 } + +      1 - (ss_err / ss_tot) +    end + +    ## +    # To fit a functional form: y = ae^(bx). +    # +    # Takes x and y values and returns [a, b, r^2]. +    # +    # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html + +    def fit_exponential xs, ys +      n     = xs.size +      xys   = xs.zip(ys) +      sxlny = sigma(xys) { |x,y| x * Math.log(y) } +      slny  = sigma(xys) { |x,y| Math.log(y)     } +      sx2   = sigma(xys) { |x,y| x * x           } +      sx    = sigma xs + +      c = n * sx2 - sx ** 2 +      a = (slny * sx2 - sx * sxlny) / c +      b = ( n * sxlny - sx * slny ) / c + +      return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) } +    end + +    ## +    # To fit a functional form: y = a + b*ln(x). +    # +    # Takes x and y values and returns [a, b, r^2]. +    # +    # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html + +    def fit_logarithmic xs, ys +      n     = xs.size +      xys   = xs.zip(ys) +      slnx2 = sigma(xys) { |x,y| Math.log(x) ** 2 } +      slnx  = sigma(xys) { |x,y| Math.log(x)      } +      sylnx = sigma(xys) { |x,y| y * Math.log(x)  } +      sy    = sigma(xys) { |x,y| y                } + +      c = n * slnx2 - slnx ** 2 +      b = ( n * sylnx - sy * slnx ) / c +      a = (sy - b * slnx) / n + +      return a, b, fit_error(xys) { |x| a + b * Math.log(x) } +    end + + +    ## +    # Fits the functional form: a + bx. +    # +    # Takes x and y values and returns [a, b, r^2]. +    # +    # See: http://mathworld.wolfram.com/LeastSquaresFitting.html + +    def fit_linear xs, ys +      n   = xs.size +      xys = xs.zip(ys) +      sx  = sigma xs +      sy  = sigma ys +      sx2 = sigma(xs)  { |x|   x ** 2 } +      sxy = sigma(xys) { |x,y| x * y  } + +      c = n * sx2 - sx**2 +      a = (sy * sx2 - sx * sxy) / c +      b = ( n * sxy - sx * sy ) / c + +      return a, b, fit_error(xys) { |x| a + b * x } +    end + +    ## +    # To fit a functional form: y = ax^b. +    # +    # Takes x and y values and returns [a, b, r^2]. +    # +    # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html + +    def fit_power xs, ys +      n       = xs.size +      xys     = xs.zip(ys) +      slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) } +      slnx    = sigma(xs)  { |x   | Math.log(x)               } +      slny    = sigma(ys)  { |   y| Math.log(y)               } +      slnx2   = sigma(xs)  { |x   | Math.log(x) ** 2          } + +      b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2); +      a = (slny - b * slnx) / n + +      return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) } +    end + +    ## +    # Enumerates over +enum+ mapping +block+ if given, returning the +    # sum of the result. Eg: +    # +    #   sigma([1, 2, 3])                # => 1 + 2 + 3 => 7 +    #   sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14 + +    def sigma enum, &block +      enum = enum.map(&block) if block +      enum.inject { |sum, n| sum + n } +    end + +    ## +    # Returns a proc that calls the specified fit method and asserts +    # that the error is within a tolerable threshold. + +    def validation_for_fit msg, threshold +      proc do |range, times| +        a, b, rr = send "fit_#{msg}", range, times +        assert_operator rr, :>=, threshold +        [a, b, rr] +      end +    end +  end +end + +class MiniTest::Spec +  ## +  # This is used to define a new benchmark method. You usually don't +  # use this directly and is intended for those needing to write new +  # performance curve fits (eg: you need a specific polynomial fit). +  # +  # See ::bench_performance_linear for an example of how to use this. + +  def self.bench name, &block +    define_method "bench_#{name.gsub(/\W+/, '_')}", &block +  end + +  ## +  # Specifies the ranges used for benchmarking for that class. +  # +  #   bench_range do +  #     bench_exp(2, 16, 2) +  #   end +  # +  # See Unit::TestCase.bench_range for more details. + +  def self.bench_range &block +    return super unless block + +    meta = (class << self; self; end) +    meta.send :define_method, "bench_range", &block +  end + +  ## +  # Create a benchmark that verifies that the performance is linear. +  # +  #   describe "my class" do +  #     bench_performance_linear "fast_algorithm", 0.9999 do |n| +  #       @obj.fast_algorithm(n) +  #     end +  #   end + +  def self.bench_performance_linear name, threshold = 0.99, &work +    bench name do +      assert_performance_linear threshold, &work +    end +  end + +  ## +  # Create a benchmark that verifies that the performance is constant. +  # +  #   describe "my class" do +  #     bench_performance_constant "zoom_algorithm!" do |n| +  #       @obj.zoom_algorithm!(n) +  #     end +  #   end + +  def self.bench_performance_constant name, threshold = 0.99, &work +    bench name do +      assert_performance_constant threshold, &work +    end +  end + +  ## +  # Create a benchmark that verifies that the performance is exponential. +  # +  #   describe "my class" do +  #     bench_performance_exponential "algorithm" do |n| +  #       @obj.algorithm(n) +  #     end +  #   end + +  def self.bench_performance_exponential name, threshold = 0.99, &work +    bench name do +      assert_performance_exponential threshold, &work +    end +  end +end diff --git a/jni/ruby/test/lib/minitest/mock.rb b/jni/ruby/test/lib/minitest/mock.rb new file mode 100644 index 0000000..19acaff --- /dev/null +++ b/jni/ruby/test/lib/minitest/mock.rb @@ -0,0 +1,195 @@ +# encoding: utf-8 + +class MockExpectationError < StandardError; end # :nodoc: + +## +# A simple and clean mock object framework. + +module MiniTest # :nodoc: + +  ## +  # All mock objects are an instance of Mock + +  class Mock +    alias :__respond_to? :respond_to? + +    skip_methods = %w(object_id respond_to_missing? inspect === to_s) + +    instance_methods.each do |m| +      undef_method m unless skip_methods.include?(m.to_s) || m =~ /^__/ +    end + +    def initialize # :nodoc: +      @expected_calls = Hash.new { |calls, name| calls[name] = [] } +      @actual_calls   = Hash.new { |calls, name| calls[name] = [] } +    end + +    ## +    # Expect that method +name+ is called, optionally with +args+ or a +    # +blk+, and returns +retval+. +    # +    #   @mock.expect(:meaning_of_life, 42) +    #   @mock.meaning_of_life # => 42 +    # +    #   @mock.expect(:do_something_with, true, [some_obj, true]) +    #   @mock.do_something_with(some_obj, true) # => true +    # +    #   @mock.expect(:do_something_else, true) do |a1, a2| +    #     a1 == "buggs" && a2 == :bunny +    #   end +    # +    # +args+ is compared to the expected args using case equality (ie, the +    # '===' operator), allowing for less specific expectations. +    # +    #   @mock.expect(:uses_any_string, true, [String]) +    #   @mock.uses_any_string("foo") # => true +    #   @mock.verify  # => true +    # +    #   @mock.expect(:uses_one_string, true, ["foo"] +    #   @mock.uses_one_string("bar") # => true +    #   @mock.verify  # => raises MockExpectationError + +    def expect(name, retval, args=[], &blk) +      if block_given? +        raise ArgumentError, "args ignored when block given" unless args.empty? +        @expected_calls[name] << { :retval => retval, :block => blk } +      else +        raise ArgumentError, "args must be an array" unless Array === args +        @expected_calls[name] << { :retval => retval, :args => args } +      end +      self +    end + +    def __call name, data # :nodoc: +      case data +      when Hash then +        "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}" +      else +        data.map { |d| __call name, d }.join ", " +      end +    end + +    ## +    # Verify that all methods were called as expected. Raises +    # +MockExpectationError+ if the mock object was not called as +    # expected. + +    def verify +      @expected_calls.each do |name, calls| +        calls.each do |expected| +          msg1 = "expected #{__call name, expected}" +          msg2 = "#{msg1}, got [#{__call name, @actual_calls[name]}]" + +          raise MockExpectationError, msg2 if +            @actual_calls.has_key?(name) and +            not @actual_calls[name].include?(expected) + +          raise MockExpectationError, msg1 unless +            @actual_calls.has_key?(name) and +            @actual_calls[name].include?(expected) +        end +      end +      true +    end + +    def method_missing(sym, *args) # :nodoc: +      unless @expected_calls.has_key?(sym) then +        raise NoMethodError, "unmocked method %p, expected one of %p" % +          [sym, @expected_calls.keys.sort_by(&:to_s)] +      end + +      index = @actual_calls[sym].length +      expected_call = @expected_calls[sym][index] + +      unless expected_call then +        raise MockExpectationError, "No more expects available for %p: %p" % +          [sym, args] +      end + +      expected_args, retval, val_block = +        expected_call.values_at(:args, :retval, :block) + +      if val_block then +        raise MockExpectationError, "mocked method %p failed block w/ %p" % +          [sym, args] unless val_block.call(args) + +        # keep "verify" happy +        @actual_calls[sym] << expected_call +        return retval +      end + +      if expected_args.size != args.size then +        raise ArgumentError, "mocked method %p expects %d arguments, got %d" % +          [sym, expected_args.size, args.size] +      end + +      fully_matched = expected_args.zip(args).all? { |mod, a| +        mod === a or mod == a +      } + +      unless fully_matched then +        raise MockExpectationError, "mocked method %p called with unexpected arguments %p" % +          [sym, args] +      end + +      @actual_calls[sym] << { +        :retval => retval, +        :args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a } +      } + +      retval +    end + +    def respond_to?(sym, include_private = false) # :nodoc: +      return true if @expected_calls.has_key?(sym.to_sym) +      return __respond_to?(sym, include_private) +    end +  end +end + +class Object # :nodoc: + +  ## +  # Add a temporary stubbed method replacing +name+ for the duration +  # of the +block+. If +val_or_callable+ responds to #call, then it +  # returns the result of calling it, otherwise returns the value +  # as-is. Cleans up the stub at the end of the +block+. The method +  # +name+ must exist before stubbing. +  # +  #     def test_stale_eh +  #       obj_under_test = Something.new +  #       refute obj_under_test.stale? +  # +  #       Time.stub :now, Time.at(0) do +  #         assert obj_under_test.stale? +  #       end +  #     end + +  def stub name, val_or_callable, &block +    new_name = "__minitest_stub__#{name}" + +    metaclass = class << self; self; end + +    if respond_to? name and not methods.map(&:to_s).include? name.to_s then +      metaclass.send :define_method, name do |*args| +        super(*args) +      end +    end + +    metaclass.send :alias_method, new_name, name + +    metaclass.send :define_method, name do |*args| +      if val_or_callable.respond_to? :call then +        val_or_callable.call(*args) +      else +        val_or_callable +      end +    end + +    yield self +  ensure +    metaclass.send :undef_method, name +    metaclass.send :alias_method, name, new_name +    metaclass.send :undef_method, new_name +  end +end diff --git a/jni/ruby/test/lib/minitest/unit.rb b/jni/ruby/test/lib/minitest/unit.rb new file mode 100644 index 0000000..0a6558d --- /dev/null +++ b/jni/ruby/test/lib/minitest/unit.rb @@ -0,0 +1,1419 @@ +# encoding: utf-8 + +require "optparse" +require "rbconfig" +require "leakchecker" + +## +# Minimal (mostly drop-in) replacement for test-unit. +# +# :include: README.txt + +module MiniTest + +  def self.const_missing name # :nodoc: +    case name +    when :MINI_DIR then +      msg = "MiniTest::MINI_DIR was removed. Don't violate other's internals." +      warn "WAR\NING: #{msg}" +      warn "WAR\NING: Used by #{caller.first}." +      const_set :MINI_DIR, "bad value" +    else +      super +    end +  end + +  ## +  # Assertion base class + +  class Assertion < Exception; end + +  ## +  # Assertion raised when skipping a test + +  class Skip < Assertion; end + +  class << self +    ## +    # Filter object for backtraces. + +    attr_accessor :backtrace_filter +  end + +  class BacktraceFilter # :nodoc: +    def filter bt +      return ["No backtrace"] unless bt + +      new_bt = [] + +      unless $DEBUG then +        bt.each do |line| +          break if line =~ /lib\/minitest/ +          new_bt << line +        end + +        new_bt = bt.reject { |line| line =~ /lib\/minitest/ } if new_bt.empty? +        new_bt = bt.dup if new_bt.empty? +      else +        new_bt = bt.dup +      end + +      new_bt +    end +  end + +  self.backtrace_filter = BacktraceFilter.new + +  def self.filter_backtrace bt # :nodoc: +    backtrace_filter.filter bt +  end + +  ## +  # MiniTest Assertions.  All assertion methods accept a +msg+ which is +  # printed if the assertion fails. + +  module Assertions +    UNDEFINED = Object.new # :nodoc: + +    def UNDEFINED.inspect # :nodoc: +      "UNDEFINED" # again with the rdoc bugs... :( +    end + +    ## +    # Returns the diff command to use in #diff. Tries to intelligently +    # figure out what diff to use. + +    def self.diff +      @diff = if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ && +                  system("diff.exe", __FILE__, __FILE__)) then +                "diff.exe -u" +              elsif Minitest::Unit::Guard.maglev? then # HACK +                "diff -u" +              elsif system("gdiff", __FILE__, __FILE__) +                "gdiff -u" # solaris and kin suck +              elsif system("diff", __FILE__, __FILE__) +                "diff -u" +              else +                nil +              end unless defined? @diff + +      @diff +    end + +    ## +    # Set the diff command to use in #diff. + +    def self.diff= o +      @diff = o +    end + +    ## +    # Returns a diff between +exp+ and +act+. If there is no known +    # diff command or if it doesn't make sense to diff the output +    # (single line, short output), then it simply returns a basic +    # comparison between the two. + +    def diff exp, act +      require "tempfile" + +      expect = mu_pp_for_diff exp +      butwas = mu_pp_for_diff act +      result = nil + +      need_to_diff = +        MiniTest::Assertions.diff && +        (expect.include?("\n")    || +         butwas.include?("\n")    || +         expect.size > 30         || +         butwas.size > 30         || +         expect == butwas) + +      return "Expected: #{mu_pp exp}\n  Actual: #{mu_pp act}" unless +        need_to_diff + +      tempfile_a = nil +      tempfile_b = nil + +      Tempfile.open("expect") do |a| +        tempfile_a = a +        a.puts expect +        a.flush + +        Tempfile.open("butwas") do |b| +          tempfile_b = b +          b.puts butwas +          b.flush + +          result = `#{MiniTest::Assertions.diff} #{a.path} #{b.path}` +          result.sub!(/^\-\-\- .+/, "--- expected") +          result.sub!(/^\+\+\+ .+/, "+++ actual") + +          if result.empty? then +            klass = exp.class +            result = [ +                      "No visible difference in the #{klass}#inspect output.\n", +                      "You should look at the implementation of #== on ", +                      "#{klass} or its members.\n", +                      expect, +                     ].join +          end +        end +      end + +      result +    ensure +      tempfile_a.close! if tempfile_a +      tempfile_b.close! if tempfile_b +    end + +    ## +    # This returns a human-readable version of +obj+. By default +    # #inspect is called. You can override this to use #pretty_print +    # if you want. + +    def mu_pp obj +      s = obj.inspect +      s = s.encode Encoding.default_external if defined? Encoding +      s +    end + +    ## +    # This returns a diff-able human-readable version of +obj+. This +    # differs from the regular mu_pp because it expands escaped +    # newlines and makes hex-values generic (like object_ids). This +    # uses mu_pp to do the first pass and then cleans it up. + +    def mu_pp_for_diff obj +      mu_pp(obj).gsub(/\\n/, "\n").gsub(/:0x[a-fA-F0-9]{4,}/m, ':0xXXXXXX') +    end + +    def _assertions= n # :nodoc: +      @_assertions = n +    end + +    def _assertions # :nodoc: +      @_assertions ||= 0 +    end + +    ## +    # Fails unless +test+ is a true value. + +    def assert test, msg = nil +      msg ||= "Failed assertion, no message given." +      self._assertions += 1 +      unless test then +        msg = msg.call if Proc === msg +        raise MiniTest::Assertion, msg +      end +      true +    end + +    ## +    # Fails unless +obj+ is empty. + +    def assert_empty obj, msg = nil +      msg = message(msg) { "Expected #{mu_pp(obj)} to be empty" } +      assert_respond_to obj, :empty? +      assert obj.empty?, msg +    end + +    ## +    # Fails unless <tt>exp == act</tt> printing the difference between +    # the two, if possible. +    # +    # If there is no visible difference but the assertion fails, you +    # should suspect that your #== is buggy, or your inspect output is +    # missing crucial details. +    # +    # For floats use assert_in_delta. +    # +    # See also: MiniTest::Assertions.diff + +    def assert_equal exp, act, msg = nil +      msg = message(msg, "") { diff exp, act } +      assert exp == act, msg +    end + +    ## +    # For comparing Floats.  Fails unless +exp+ and +act+ are within +delta+ +    # of each other. +    # +    #   assert_in_delta Math::PI, (22.0 / 7.0), 0.01 + +    def assert_in_delta exp, act, delta = 0.001, msg = nil +      n = (exp - act).abs +      msg = message(msg) { +        "Expected |#{exp} - #{act}| (#{n}) to be <= #{delta}" +      } +      assert delta >= n, msg +    end + +    ## +    # For comparing Floats.  Fails unless +exp+ and +act+ have a relative +    # error less than +epsilon+. + +    def assert_in_epsilon a, b, epsilon = 0.001, msg = nil +      assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg +    end + +    ## +    # Fails unless +collection+ includes +obj+. + +    def assert_includes collection, obj, msg = nil +      msg = message(msg) { +        "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" +      } +      assert_respond_to collection, :include? +      assert collection.include?(obj), msg +    end + +    ## +    # Fails unless +obj+ is an instance of +cls+. + +    def assert_instance_of cls, obj, msg = nil +      msg = message(msg) { +        "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" +      } + +      assert obj.instance_of?(cls), msg +    end + +    ## +    # Fails unless +obj+ is a kind of +cls+. + +    def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of +      msg = message(msg) { +        "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" } + +      assert obj.kind_of?(cls), msg +    end + +    ## +    # Fails unless +matcher+ <tt>=~</tt> +obj+. + +    def assert_match matcher, obj, msg = nil +      msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" } +      assert_respond_to matcher, :"=~" +      matcher = Regexp.new Regexp.escape matcher if String === matcher +      assert matcher =~ obj, msg +    end + +    ## +    # Fails unless +obj+ is nil + +    def assert_nil obj, msg = nil +      msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" } +      assert obj.nil?, msg +    end + +    ## +    # For testing with binary operators. +    # +    #   assert_operator 5, :<=, 4 + +    def assert_operator o1, op, o2 = UNDEFINED, msg = nil +      return assert_predicate o1, op, msg if UNDEFINED == o2 +      msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" } +      assert o1.__send__(op, o2), msg +    end + +    ## +    # Fails if stdout or stderr do not output the expected results. +    # Pass in nil if you don't care about that streams output. Pass in +    # "" if you require it to be silent. Pass in a regexp if you want +    # to pattern match. +    # +    # NOTE: this uses #capture_io, not #capture_subprocess_io. +    # +    # See also: #assert_silent + +    def assert_output stdout = nil, stderr = nil +      out, err = capture_io do +        yield +      end + +      err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr +      out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout + +      y = send err_msg, stderr, err, "In stderr" if err_msg +      x = send out_msg, stdout, out, "In stdout" if out_msg + +      (!stdout || x) && (!stderr || y) +    end + +    ## +    # For testing with predicates. +    # +    #   assert_predicate str, :empty? +    # +    # This is really meant for specs and is front-ended by assert_operator: +    # +    #   str.must_be :empty? + +    def assert_predicate o1, op, msg = nil +      msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" } +      assert o1.__send__(op), msg +    end + +    ## +    # Fails unless the block raises one of +exp+. Returns the +    # exception matched so you can check the message, attributes, etc. + +    def assert_raises *exp +      msg = "#{exp.pop}.\n" if String === exp.last + +      begin +        yield +      rescue MiniTest::Skip => e +        return e if exp.include? MiniTest::Skip +        raise e +      rescue Exception => e +        expected = exp.any? { |ex| +          if ex.instance_of? Module then +            e.kind_of? ex +          else +            e.instance_of? ex +          end +        } + +        assert expected, proc { +          exception_details(e, "#{msg}#{mu_pp(exp)} exception expected, not") +        } + +        return e +      end + +      exp = exp.first if exp.size == 1 + +      flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." +    end + +    ## +    # Fails unless +obj+ responds to +meth+. + +    def assert_respond_to obj, meth, msg = nil +      msg = message(msg) { +        "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}" +      } +      assert obj.respond_to?(meth), msg +    end + +    ## +    # Fails unless +exp+ and +act+ are #equal? + +    def assert_same exp, act, msg = nil +      msg = message(msg) { +        data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] +        "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data +      } +      assert exp.equal?(act), msg +    end + +    ## +    # +send_ary+ is a receiver, message and arguments. +    # +    # Fails unless the call returns a true value +    # TODO: I should prolly remove this from specs + +    def assert_send send_ary, m = nil +      recv, msg, *args = send_ary +      m = message(m) { +        "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" } +      assert recv.__send__(msg, *args), m +    end + +    ## +    # Fails if the block outputs anything to stderr or stdout. +    # +    # See also: #assert_output + +    def assert_silent +      assert_output "", "" do +        yield +      end +    end + +    ## +    # Fails unless the block throws +sym+ + +    def assert_throws sym, msg = nil +      default = "Expected #{mu_pp(sym)} to have been thrown" +      caught = true +      catch(sym) do +        begin +          yield +        rescue ThreadError => e       # wtf?!? 1.8 + threads == suck +          default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}" +        rescue ArgumentError => e     # 1.9 exception +          default += ", not #{e.message.split(/ /).last}" +        rescue NameError => e         # 1.8 exception +          default += ", not #{e.name.inspect}" +        end +        caught = false +      end + +      assert caught, message(msg) { default } +    end + +    ## +    # Captures $stdout and $stderr into strings: +    # +    #   out, err = capture_io do +    #     puts "Some info" +    #     warn "You did a bad thing" +    #   end +    # +    #   assert_match %r%info%, out +    #   assert_match %r%bad%, err +    # +    # NOTE: For efficiency, this method uses StringIO and does not +    # capture IO for subprocesses. Use #capture_subprocess_io for +    # that. + +    def capture_io +      require 'stringio' + +      captured_stdout, captured_stderr = StringIO.new, StringIO.new + +      synchronize do +        orig_stdout, orig_stderr = $stdout, $stderr +        $stdout, $stderr         = captured_stdout, captured_stderr + +        begin +          yield +        ensure +          $stdout = orig_stdout +          $stderr = orig_stderr +        end +      end + +      return captured_stdout.string, captured_stderr.string +    end + +    ## +    # Captures $stdout and $stderr into strings, using Tempfile to +    # ensure that subprocess IO is captured as well. +    # +    #   out, err = capture_subprocess_io do +    #     system "echo Some info" +    #     system "echo You did a bad thing 1>&2" +    #   end +    # +    #   assert_match %r%info%, out +    #   assert_match %r%bad%, err +    # +    # NOTE: This method is approximately 10x slower than #capture_io so +    # only use it when you need to test the output of a subprocess. + +    def capture_subprocess_io +      require 'tempfile' + +      captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err") + +      synchronize do +        orig_stdout, orig_stderr = $stdout.dup, $stderr.dup +        $stdout.reopen captured_stdout +        $stderr.reopen captured_stderr + +        begin +          yield + +          $stdout.rewind +          $stderr.rewind + +          [captured_stdout.read, captured_stderr.read] +        ensure +          $stdout.reopen orig_stdout +          $stderr.reopen orig_stderr +          orig_stdout.close +          orig_stderr.close +          captured_stdout.close! +          captured_stderr.close! +        end +      end +    end + +    ## +    # Returns details for exception +e+ + +    def exception_details e, msg +      [ +       "#{msg}", +       "Class: <#{e.class}>", +       "Message: <#{e.message.inspect}>", +       "---Backtrace---", +       "#{MiniTest::filter_backtrace(e.backtrace).join("\n")}", +       "---------------", +      ].join "\n" +    end + +    ## +    # Fails with +msg+ + +    def flunk msg = nil +      msg ||= "Epic Fail!" +      assert false, msg +    end + +    ## +    # Returns a proc that will output +msg+ along with the default message. + +    def message msg = nil, ending = ".", &default +      proc { +        msg = msg.call.chomp(".") if Proc === msg +        custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty? +        "#{custom_message}#{default.call}#{ending}" +      } +    end + +    ## +    # used for counting assertions + +    def pass msg = nil +      assert true +    end + +    ## +    # Fails if +test+ is a true value + +    def refute test, msg = nil +      msg ||= "Failed refutation, no message given" +      not assert(! test, msg) +    end + +    ## +    # Fails if +obj+ is empty. + +    def refute_empty obj, msg = nil +      msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" } +      assert_respond_to obj, :empty? +      refute obj.empty?, msg +    end + +    ## +    # Fails if <tt>exp == act</tt>. +    # +    # For floats use refute_in_delta. + +    def refute_equal exp, act, msg = nil +      msg = message(msg) { +        "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" +      } +      refute exp == act, msg +    end + +    ## +    # For comparing Floats.  Fails if +exp+ is within +delta+ of +act+. +    # +    #   refute_in_delta Math::PI, (22.0 / 7.0) + +    def refute_in_delta exp, act, delta = 0.001, msg = nil +      n = (exp - act).abs +      msg = message(msg) { +        "Expected |#{exp} - #{act}| (#{n}) to not be <= #{delta}" +      } +      refute delta >= n, msg +    end + +    ## +    # For comparing Floats.  Fails if +exp+ and +act+ have a relative error +    # less than +epsilon+. + +    def refute_in_epsilon a, b, epsilon = 0.001, msg = nil +      refute_in_delta a, b, a * epsilon, msg +    end + +    ## +    # Fails if +collection+ includes +obj+. + +    def refute_includes collection, obj, msg = nil +      msg = message(msg) { +        "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" +      } +      assert_respond_to collection, :include? +      refute collection.include?(obj), msg +    end + +    ## +    # Fails if +obj+ is an instance of +cls+. + +    def refute_instance_of cls, obj, msg = nil +      msg = message(msg) { +        "Expected #{mu_pp(obj)} to not be an instance of #{cls}" +      } +      refute obj.instance_of?(cls), msg +    end + +    ## +    # Fails if +obj+ is a kind of +cls+. + +    def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of +      msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" } +      refute obj.kind_of?(cls), msg +    end + +    ## +    # Fails if +matcher+ <tt>=~</tt> +obj+. + +    def refute_match matcher, obj, msg = nil +      msg = message(msg) {"Expected #{mu_pp matcher} to not match #{mu_pp obj}"} +      assert_respond_to matcher, :"=~" +      matcher = Regexp.new Regexp.escape matcher if String === matcher +      refute matcher =~ obj, msg +    end + +    ## +    # Fails if +obj+ is nil. + +    def refute_nil obj, msg = nil +      msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" } +      refute obj.nil?, msg +    end + +    ## +    # Fails if +o1+ is not +op+ +o2+. Eg: +    # +    #   refute_operator 1, :>, 2 #=> pass +    #   refute_operator 1, :<, 2 #=> fail + +    def refute_operator o1, op, o2 = UNDEFINED, msg = nil +      return refute_predicate o1, op, msg if UNDEFINED == o2 +      msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"} +      refute o1.__send__(op, o2), msg +    end + +    ## +    # For testing with predicates. +    # +    #   refute_predicate str, :empty? +    # +    # This is really meant for specs and is front-ended by refute_operator: +    # +    #   str.wont_be :empty? + +    def refute_predicate o1, op, msg = nil +      msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" } +      refute o1.__send__(op), msg +    end + +    ## +    # Fails if +obj+ responds to the message +meth+. + +    def refute_respond_to obj, meth, msg = nil +      msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" } + +      refute obj.respond_to?(meth), msg +    end + +    ## +    # Fails if +exp+ is the same (by object identity) as +act+. + +    def refute_same exp, act, msg = nil +      msg = message(msg) { +        data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] +        "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data +      } +      refute exp.equal?(act), msg +    end + +    ## +    # Skips the current test. Gets listed at the end of the run but +    # doesn't cause a failure exit code. + +    def skip msg = nil, bt = caller +      msg ||= "Skipped, no message given" +      @skip = true +      raise MiniTest::Skip, msg, bt +    end + +    ## +    # Was this testcase skipped? Meant for #teardown. + +    def skipped? +      defined?(@skip) and @skip +    end + +    ## +    # Takes a block and wraps it with the runner's shared mutex. + +    def synchronize +      Minitest::Unit.runner.synchronize do +        yield +      end +    end +  end + +  class Unit # :nodoc: +    VERSION = "4.7.5" # :nodoc: + +    attr_accessor :report, :failures, :errors, :skips # :nodoc: +    attr_accessor :assertion_count                    # :nodoc: +    attr_writer   :test_count                         # :nodoc: +    attr_accessor :start_time                         # :nodoc: +    attr_accessor :help                               # :nodoc: +    attr_accessor :verbose                            # :nodoc: +    attr_writer   :options                            # :nodoc: + +    ## +    # :attr: +    # +    # if true, installs an "INFO" signal handler (only available to BSD and +    # OS X users) which prints diagnostic information about the test run. +    # +    # This is auto-detected by default but may be overridden by custom +    # runners. + +    attr_accessor :info_signal + +    ## +    # Lazy accessor for options. + +    def options +      @options ||= {} +    end + +    @@installed_at_exit ||= false +    @@out = $stdout +    @@after_tests = [] + +    ## +    # A simple hook allowing you to run a block of code after _all_ of +    # the tests are done. Eg: +    # +    #   MiniTest::Unit.after_tests { p $debugging_info } + +    def self.after_tests &block +      @@after_tests << block +    end + +    ## +    # Registers MiniTest::Unit to run tests at process exit + +    def self.autorun +      at_exit { +        # don't run if there was a non-exit exception +        next if $! and not $!.kind_of? SystemExit + +        # the order here is important. The at_exit handler must be +        # installed before anyone else gets a chance to install their +        # own, that way we can be assured that our exit will be last +        # to run (at_exit stacks). +        exit_code = nil + +        at_exit { +          @@after_tests.reverse_each(&:call) +          exit false if exit_code && exit_code != 0 +        } + +        exit_code = MiniTest::Unit.new.run ARGV +      } unless @@installed_at_exit +      @@installed_at_exit = true +    end + +    ## +    # Returns the stream to use for output. + +    def self.output +      @@out +    end + +    ## +    # Sets MiniTest::Unit to write output to +stream+.  $stdout is the default +    # output + +    def self.output= stream +      @@out = stream +    end + +    ## +    # Tells MiniTest::Unit to delegate to +runner+, an instance of a +    # MiniTest::Unit subclass, when MiniTest::Unit#run is called. + +    def self.runner= runner +      @@runner = runner +    end + +    ## +    # Returns the MiniTest::Unit subclass instance that will be used +    # to run the tests. A MiniTest::Unit instance is the default +    # runner. + +    def self.runner +      @@runner ||= self.new +    end + +    ## +    # Return all plugins' run methods (methods that start with "run_"). + +    def self.plugins +      @@plugins ||= (["run_tests"] + +                     public_instance_methods(false). +                     grep(/^run_/).map { |s| s.to_s }).uniq +    end + +    ## +    # Return the IO for output. + +    def output +      self.class.output +    end + +    def puts *a  # :nodoc: +      output.puts(*a) +    end + +    def print *a # :nodoc: +      output.print(*a) +    end + +    def test_count # :nodoc: +      @test_count ||= 0 +    end + +    ## +    # Runner for a given +type+ (eg, test vs bench). + +    def _run_anything type +      suites = TestCase.send "#{type}_suites" +      return if suites.empty? + +      start = Time.now + +      puts +      puts "# Running #{type}s:" +      puts + +      @test_count, @assertion_count = 0, 0 +      sync = output.respond_to? :"sync=" # stupid emacs +      old_sync, output.sync = output.sync, true if sync + +      results = _run_suites suites, type + +      @test_count      = results.inject(0) { |sum, (tc, _)| sum + tc } +      @assertion_count = results.inject(0) { |sum, (_, ac)| sum + ac } + +      output.sync = old_sync if sync + +      t = Time.now - start + +      puts +      puts +      puts "Finished #{type}s in %.6fs, %.4f tests/s, %.4f assertions/s." % +        [t, test_count / t, assertion_count / t] + +      report.each_with_index do |msg, i| +        puts "\n%3d) %s" % [i + 1, msg] +      end + +      puts + +      status +    end + +    ## +    # Runs all the +suites+ for a given +type+. +    # + +    def _run_suites suites, type +      suites.map { |suite| _run_suite suite, type } +    end + +    ## +    # Run a single +suite+ for a given +type+. + +    def _run_suite suite, type +      header = "#{type}_suite_header" +      puts send(header, suite) if respond_to? header + +      filter = options[:filter] || '/./' +      filter = Regexp.new $1 if filter =~ /\/(.*)\// + +      all_test_methods = suite.send "#{type}_methods" + +      filtered_test_methods = all_test_methods.find_all { |m| +        filter === m || filter === "#{suite}##{m}" +      } + +      leakchecker = LeakChecker.new + +      assertions = filtered_test_methods.map { |method| +        inst = suite.new method +        inst._assertions = 0 + +        print "#{suite}##{method} = " if @verbose + +        start_time = Time.now if @verbose +        result = inst.run self + +        print "%.2f s = " % (Time.now - start_time) if @verbose +        print result +        puts if @verbose +        $stdout.flush + +        leakchecker.check("#{inst.class}\##{inst.__name__}") + +        inst._assertions +      } + +      return assertions.size, assertions.inject(0) { |sum, n| sum + n } +    end + +    ## +    # Record the result of a single test. Makes it very easy to gather +    # information. Eg: +    # +    #   class StatisticsRecorder < MiniTest::Unit +    #     def record suite, method, assertions, time, error +    #       # ... record the results somewhere ... +    #     end +    #   end +    # +    #   MiniTest::Unit.runner = StatisticsRecorder.new +    # +    # NOTE: record might be sent more than once per test.  It will be +    # sent once with the results from the test itself.  If there is a +    # failure or error in teardown, it will be sent again with the +    # error or failure. + +    def record suite, method, assertions, time, error +    end + +    def location e # :nodoc: +      last_before_assertion = "" +      e.backtrace.reverse_each do |s| +        break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/ +        last_before_assertion = s +      end +      last_before_assertion.sub(/:in .*$/, '') +    end + +    ## +    # Writes status for failed test +meth+ in +klass+ which finished with +    # exception +e+ + +    def puke klass, meth, e +      e = case e +          when MiniTest::Skip then +            @skips += 1 +            return "S" unless @verbose +            "Skipped:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" +          when MiniTest::Assertion then +            @failures += 1 +            "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" +          else +            @errors += 1 +            bt = MiniTest::filter_backtrace(e.backtrace).join "\n    " +            "Error:\n#{klass}##{meth}:\n#{e.class}: #{e.message}\n    #{bt}\n" +          end +      @report << e +      e[0, 1] +    end + +    def initialize # :nodoc: +      @report = [] +      @errors = @failures = @skips = 0 +      @verbose = false +      @mutex = defined?(Mutex) ? Mutex.new : nil +      @info_signal = Signal.list['INFO'] +    end + +    def synchronize # :nodoc: +      if @mutex then +        @mutex.synchronize { yield } +      else +        yield +      end +    end + +    def process_args args = [] # :nodoc: +      options = {} +      orig_args = args.dup + +      OptionParser.new do |opts| +        opts.banner  = 'minitest options:' +        opts.version = MiniTest::Unit::VERSION + +        opts.on '-h', '--help', 'Display this help.' do +          puts opts +          exit +        end + +        opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m| +          options[:seed] = m.to_i +        end + +        opts.on '-v', '--verbose', "Verbose. Show progress processing files." do +          options[:verbose] = true +        end + +        opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |a| +          options[:filter] = a +        end + +        opts.parse! args +        orig_args -= args +      end + +      unless options[:seed] then +        srand +        options[:seed] = srand % 0xFFFF +        orig_args << "--seed" << options[:seed].to_s +      end + +      srand options[:seed] + +      self.verbose = options[:verbose] +      @help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " " + +      options +    end + +    ## +    # Begins the full test run. Delegates to +runner+'s #_run method. + +    def run args = [] +      self.class.runner._run(args) +    end + +    ## +    # Top level driver, controls all output and filtering. + +    def _run args = [] +      args = process_args args # ARGH!! blame test/unit process_args +      self.options.merge! args + +      puts "Run options: #{help}" + +      self.class.plugins.each do |plugin| +        send plugin +        break unless report.empty? +      end + +      return failures + errors if self.test_count > 0 # or return nil... +    rescue Interrupt +      abort 'Interrupted' +    end + +    ## +    # Runs test suites matching +filter+. + +    def run_tests +      _run_anything :test +    end + +    ## +    # Writes status to +io+ + +    def status io = self.output +      format = "%d tests, %d assertions, %d failures, %d errors, %d skips" +      io.puts format % [test_count, assertion_count, failures, errors, skips] +    end + +    ## +    # Provides a simple set of guards that you can use in your tests +    # to skip execution if it is not applicable. These methods are +    # mixed into TestCase as both instance and class methods so you +    # can use them inside or outside of the test methods. +    # +    #   def test_something_for_mri +    #     skip "bug 1234"  if jruby? +    #     # ... +    #   end +    # +    #   if windows? then +    #     # ... lots of test methods ... +    #   end + +    module Guard + +      ## +      # Is this running on jruby? + +      def jruby? platform = RUBY_PLATFORM +        "java" == platform +      end + +      ## +      # Is this running on mri? + +      def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE +        "maglev" == platform +      end + +      module_function :maglev? + +      ## +      # Is this running on mri? + +      def mri? platform = RUBY_DESCRIPTION +        /^ruby/ =~ platform +      end + +      ## +      # Is this running on rubinius? + +      def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE +        "rbx" == platform +      end + +      ## +      # Is this running on windows? + +      def windows? platform = RUBY_PLATFORM +        /mswin|mingw/ =~ platform +      end +    end + +    ## +    # Provides before/after hooks for setup and teardown. These are +    # meant for library writers, NOT for regular test authors. See +    # #before_setup for an example. + +    module LifecycleHooks +      ## +      # Runs before every test, after setup. This hook is meant for +      # libraries to extend minitest. It is not meant to be used by +      # test developers. +      # +      # See #before_setup for an example. + +      def after_setup; end + +      ## +      # Runs before every test, before setup. This hook is meant for +      # libraries to extend minitest. It is not meant to be used by +      # test developers. +      # +      # As a simplistic example: +      # +      #   module MyMinitestPlugin +      #     def before_setup +      #       super +      #       # ... stuff to do before setup is run +      #     end +      # +      #     def after_setup +      #       # ... stuff to do after setup is run +      #       super +      #     end +      # +      #     def before_teardown +      #       super +      #       # ... stuff to do before teardown is run +      #     end +      # +      #     def after_teardown +      #       # ... stuff to do after teardown is run +      #       super +      #     end +      #   end +      # +      #   class MiniTest::Unit::TestCase +      #     include MyMinitestPlugin +      #   end + +      def before_setup; end + +      ## +      # Runs after every test, before teardown. This hook is meant for +      # libraries to extend minitest. It is not meant to be used by +      # test developers. +      # +      # See #before_setup for an example. + +      def before_teardown; end + +      ## +      # Runs after every test, after teardown. This hook is meant for +      # libraries to extend minitest. It is not meant to be used by +      # test developers. +      # +      # See #before_setup for an example. + +      def after_teardown; end +    end + +    ## +    # Subclass TestCase to create your own tests. Typically you'll want a +    # TestCase subclass per implementation class. +    # +    # See MiniTest::Assertions + +    class TestCase +      include LifecycleHooks +      include Guard +      extend Guard + +      attr_reader :__name__ # :nodoc: + +      PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, +                                Interrupt, SystemExit] # :nodoc: + +      ## +      # Runs the tests reporting the status to +runner+ + +      def run runner +        trap "INFO" do +          runner.report.each_with_index do |msg, i| +            warn "\n%3d) %s" % [i + 1, msg] +          end +          warn '' +          time = runner.start_time ? Time.now - runner.start_time : 0 +          warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time] +          runner.status $stderr +        end if runner.info_signal + +        start_time = Time.now + +        result = "" +        begin +          @passed = nil +          self.before_setup +          self.setup +          self.after_setup +          self.run_test self.__name__ +          result = "." unless io? +          time = Time.now - start_time +          runner.record self.class, self.__name__, self._assertions, time, nil +          @passed = true +        rescue *PASSTHROUGH_EXCEPTIONS +          raise +        rescue Exception => e +          @passed = Skip === e +          time = Time.now - start_time +          runner.record self.class, self.__name__, self._assertions, time, e +          result = runner.puke self.class, self.__name__, e +        ensure +          %w{ before_teardown teardown after_teardown }.each do |hook| +            begin +              self.send hook +            rescue *PASSTHROUGH_EXCEPTIONS +              raise +            rescue Exception => e +              @passed = false +              runner.record self.class, self.__name__, self._assertions, time, e +              result = runner.puke self.class, self.__name__, e +            end +          end +          trap 'INFO', 'DEFAULT' if runner.info_signal +        end +        result +      end + +      alias :run_test :__send__ + +      def initialize name # :nodoc: +        @__name__ = name +        @__io__ = nil +        @passed = nil +        @@current = self # FIX: make thread local +      end + +      def self.current # :nodoc: +        @@current # FIX: make thread local +      end + +      ## +      # Return the output IO object + +      def io +        @__io__ = true +        MiniTest::Unit.output +      end + +      ## +      # Have we hooked up the IO yet? + +      def io? +        @__io__ +      end + +      def self.reset # :nodoc: +        @@test_suites = {} +      end + +      reset + +      ## +      # Call this at the top of your tests when you absolutely +      # positively need to have ordered tests. In doing so, you're +      # admitting that you suck and your tests are weak. + +      def self.i_suck_and_my_tests_are_order_dependent! +        class << self +          undef_method :test_order if method_defined? :test_order +          define_method :test_order do :alpha end +        end +      end + +      ## +      # Make diffs for this TestCase use #pretty_inspect so that diff +      # in assert_equal can be more details. NOTE: this is much slower +      # than the regular inspect but much more usable for complex +      # objects. + +      def self.make_my_diffs_pretty! +        require 'pp' + +        define_method :mu_pp do |o| +          o.pretty_inspect +        end +      end + +      def self.inherited klass # :nodoc: +        @@test_suites[klass] = true +        super +      end + +      def self.test_order # :nodoc: +        :random +      end + +      def self.test_suites # :nodoc: +        @@test_suites.keys.sort_by { |ts| ts.name.to_s } +      end + +      def self.test_methods # :nodoc: +        methods = public_instance_methods(true).grep(/^test/).map { |m| m.to_s } + +        case self.test_order +        when :parallel +          max = methods.size +          ParallelEach.new methods.sort.sort_by { rand max } +        when :random then +          max = methods.size +          methods.sort.sort_by { rand max } +        when :alpha, :sorted then +          methods.sort +        else +          raise "Unknown test_order: #{self.test_order.inspect}" +        end +      end + +      ## +      # Returns true if the test passed. + +      def passed? +        @passed +      end + +      ## +      # Runs before every test. Use this to set up before each test +      # run. + +      def setup; end + +      ## +      # Runs after every test. Use this to clean up after each test +      # run. + +      def teardown; end + +      include MiniTest::Assertions +    end # class TestCase +  end # class Unit + +  Test = Unit::TestCase +end # module MiniTest + +Minitest = MiniTest # :nodoc: because ugh... I typo this all the time | 
