├── .gitignore ├── Gemfile ├── README.md ├── Rakefile ├── em-ventually.gemspec ├── lib ├── em-ventually.rb └── em-ventually │ ├── emify.rb │ ├── eventually.rb │ ├── eventually │ ├── minitest.rb │ ├── rspec.rb │ └── testunit.rb │ ├── minitest.rb │ ├── pool.rb │ ├── rspec.rb │ ├── testunit.rb │ └── version.rb └── test ├── minitest-2.0 ├── Gemfile ├── Rakefile ├── helper.rb └── test_ventually.rb ├── rspec-2.6 ├── Gemfile ├── Rakefile ├── helper.rb └── ventually_spec.rb └── test-unit ├── Gemfile ├── Rakefile ├── helper.rb └── test_ventually.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | **/Gemfile.lock 5 | pkg/* 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in em-ventually.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EM::Ventually 2 | 3 | ## Background 4 | 5 | Your tests will eventually pass. You're not sure when, but you know it'll be quick. This is where EM::Ventually can help you! 6 | 7 | Take this trivial example. (It's in Minitest, but you can use whatever test suite you'd like*) 8 | Without em-ventually, testing your EM code requires a lot of boilerplate such as: 9 | 10 | ~~~~~ {ruby} 11 | # Without em-ventually 12 | def test_em 13 | # Start EM loop. 14 | EM.run do 15 | # The only two lines you actually care about. 16 | val = nil 17 | EM.add_timer(0.5) { val = 'test' } 18 | 19 | # Test that work happens in the future. 20 | EM.add_periodic_timer(0.1) do 21 | if val == 'test' 22 | pass # Increment assertion count. 23 | EM.stop # Manually stop EM loop. 24 | end 25 | end 26 | 27 | # Guard against infinite loops. 28 | EM.add_timer(1) { raise "Potential infinite loop averted!" } 29 | end 30 | end 31 | ~~~~~ 32 | 33 | So, you want to test that val is 'test', and as well, you want EM to start on the beginning of your test and shutdown when it's done. The other thing you want is the ability to not let this test run forever, but to shutdown EM and consider it a failure if it doesn't complete. 34 | 35 | **EM::Ventually is here to help!** 36 | 37 | `EM::Ventually` will take care to start and stop EventMachine, and make sure your tests run serially (unless you don't want them to). It will also prevent your tests from running forever. 38 | 39 | Taking the example above you can enqueue a test. 40 | 41 | ~~~~~ {ruby} 42 | def test_em 43 | val = 'not test' 44 | EM.add_timer(0.5) { val = 'test' } 45 | eventually('test') { val } 46 | end 47 | ~~~~~ 48 | 49 | This will poll the block passed to eventually every 0.1 seconds to see if the condition is equal to the argument you passed in to eventually, in this case 'test'. After one second, if it's still not equal, it will fail. If you do not pass in a value for testing, it will evaluate what you return against ruby's notion of truth (not nil and not false). An exmaple: 50 | 51 | ~~~~~ {ruby} 52 | def test_em 53 | count = 0 54 | EM.add_periodic_timer(0.01) { count += 0.5 } 55 | eventually { count >= 3 } 56 | end 57 | ~~~~~ 58 | 59 | As well, you can change both the polling interval as well as the maximum execution time by passing in `:every` and `:total`. Here is an example: 60 | 61 | ~~~~~ {ruby} 62 | def test_em 63 | val = nil 64 | EM.add_timer(0.5) { val = 'test' } 65 | eventually('test', :every => 0.2, :total => 10) { val } # check every 0.2 seconds 66 | # for a total of 10 seconds. 67 | end 68 | ~~~~~ 69 | 70 | You can also parallelize tests if you don't want them to run serially. 71 | 72 | ~~~~~ {ruby} 73 | def test_em 74 | val1, val2 = nil, nil 75 | EM.add_timer(0.5) { val1 = 'test1' } 76 | EM.add_timer(0.5) { val2 = 'test2' } 77 | parallel do 78 | eventually('test1') { val1 } 79 | eventually('test2') { val2 } 80 | end 81 | end 82 | ~~~~~ 83 | 84 | Simply returning from your block doesn't always cover your test. Say for instance, you need to do a call against some sort of async client that will return your value in a callback. You can pass values back for equality by doing the following. 85 | 86 | ~~~~~ {ruby} 87 | class AsyncClient 88 | def status(&blk) 89 | EM.add_timer(0.5) do 90 | blk.call(:ok) 91 | end 92 | end 93 | end 94 | 95 | def test_em 96 | client = AsyncClient.new 97 | eventually(:ok) { |with| client.status {|status| with[status]} } 98 | # The secret sauce is in the arity of the block passed to `eventually` 99 | end 100 | ~~~~~ 101 | 102 | ## Usage 103 | 104 | Right now, `Test::Unit`, `RSpec` and `MiniTest` are supported. Just do `include EM::Ventually` in your test and you'll get all this for free. If you want to use this in all your tests, you can `require 'em-ventually/{minitest,unittest,rspec}'` your appropriate test suite. 105 | 106 | There are a couple of global options you can mess with too. `EM::Ventually.every_default=` and `EM::Ventually.total_default=` can both set global `:every` and `:total` times for your tests. 107 | 108 | If you don't pass a value to eventually, it will test that your value is true (in the ruby sense). Optionally, you can call `.test` to pass a custom tester. 109 | 110 | ~~~~~ {ruby} 111 | def test_em 112 | count = 0 113 | EM.add_periodic_timer(0.01) { count += 0.5 } 114 | eventually { count }.test{ |v| v >= 3 } 115 | end 116 | ~~~~~ 117 | 118 | of course, you're gonna be writing so many of these we've aliased it to make your tests stylish and classy. 119 | 120 | ~~~~~ {ruby} 121 | def test_em 122 | count = 0 123 | EM.add_periodic_timer(0.01) { count += 0.5 } 124 | ly { count }.test{ |v| v >= 3 } 125 | end 126 | ~~~~~ 127 | 128 | If you want to manually manage stopping and starting EM within a test, you can call `manually_stop_em!` within your test. An example: 129 | 130 | ~~~~~ {ruby} 131 | def test_em 132 | manually_stop_em! 133 | EM.add_timer(0.5) { assert "Hey!"; EM.stop } 134 | end 135 | ~~~~~ 136 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | 3 | task :default => :test 4 | task :test => [:'test:readme', :'test:suites'] 5 | 6 | matchers = { 7 | 'minitest-2.0' => [/6 tests, 9 assertions, 1 failures, 0 errors/m], 8 | 'rspec-2.6' => [/\n\.\.\.\.F\.\.\.\n/m], 9 | 'test-unit' => [/\n\.\.\.F\.\.\n/m, /test_out_of_order\(TestEMVentually\)/m] 10 | } 11 | 12 | namespace :test do 13 | task :suites do 14 | 15 | matchers.each do |type, matcher| 16 | STDOUT.sync = true 17 | Dir.chdir("./test/#{type}") do 18 | raise "You should probably run test:prepare first" unless File.exist?('./Gemfile.lock') 19 | print "Testing #{type}#{' ' * (22 - type.size )}" 20 | fork { 21 | ENV['BUNDLE_GEMFILE'] = File.expand_path("./Gemfile") 22 | out = `bundle exec rake 2>&1` 23 | if matcher.all?{|m|out[m]} 24 | exit 25 | else 26 | puts out 27 | exit 1 28 | end 29 | } 30 | _, status = Process.wait2 31 | puts status.success? ? "PASSED" : "FAILED" 32 | end 33 | end 34 | end 35 | 36 | task :readme do 37 | # test README.md 38 | puts "Testing README.md" 39 | STDOUT.sync = true 40 | readme = File.read('./README.md') 41 | passes = readme.scan(/~~~~~ \{ruby\}\n(.*?)~~~~~/m).map do |block| 42 | fork { 43 | require 'minitest/autorun' 44 | require 'eventmachine' 45 | $LOAD_PATH << 'lib' 46 | STDOUT.reopen('/dev/null') 47 | require 'em-ventually' 48 | code = block.join 49 | cls = Class.new(MiniTest::Unit::TestCase) 50 | cls.class_eval "include EM::Ventually" unless code[/# Without em-ventually/] 51 | cls.class_eval(code) 52 | cls 53 | } 54 | _, status = Process.wait2 55 | print status.success? ? '.' : 'F' 56 | status.success? ? :pass : :fail 57 | end 58 | puts 59 | pass_count = passes.inject(0){|m, s| m += (s == :pass ? 1 : 0)} 60 | raise "README tests failed" unless pass_count == passes.size 61 | end 62 | 63 | task :prepare do 64 | matchers.each do |type, matcher| 65 | puts "Preparing #{type}" 66 | Dir.chdir("./test/#{type}") do 67 | ENV['BUNDLE_GEMFILE'] = File.expand_path("./Gemfile") 68 | out = `bundle 2>&1` 69 | end 70 | end 71 | end 72 | end -------------------------------------------------------------------------------- /em-ventually.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "em-ventually/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "em-ventually" 7 | s.version = EventMachine::Ventually::VERSION 8 | s.authors = ["Josh Hull"] 9 | s.email = ["joshbuddy@gmail.com"] 10 | s.homepage = "" 11 | s.summary = %q{Eventually, your tests should pass in EventMachine} 12 | s.description = %q{Eventually, your tests should pass in EventMachine.} 13 | 14 | s.rubyforge_project = "em-ventually" 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 18 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 19 | s.require_paths = ["lib"] 20 | 21 | # dependencies 22 | s.add_runtime_dependency 'eventmachine' 23 | s.add_runtime_dependency 'callsite', '~> 0.0.5' 24 | s.add_development_dependency 'code_stats' 25 | s.add_development_dependency 'rake', '~> 0.8.7' 26 | s.add_development_dependency 'phocus' 27 | s.add_development_dependency 'minitest', '~> 2.0.0' 28 | end -------------------------------------------------------------------------------- /lib/em-ventually.rb: -------------------------------------------------------------------------------- 1 | require 'set' 2 | require 'eventmachine' 3 | require 'callsite' 4 | require 'em-ventually/eventually' 5 | require 'em-ventually/emify' 6 | require 'em-ventually/pool' 7 | require 'em-ventually/version' 8 | 9 | module EventMachine 10 | module Ventually 11 | def self.every_default=(value) 12 | @every_default = value 13 | end 14 | 15 | def self.every_default 16 | instance_variable_defined?(:@every_default) ? @every_default : 0.1 17 | end 18 | 19 | def self.total_default=(value) 20 | @total_default = value 21 | end 22 | 23 | def self.total_default 24 | instance_variable_defined?(:@total_default) ? @total_default : 1.0 25 | end 26 | 27 | def _pool 28 | @_pool ||= Pool.new 29 | end 30 | 31 | def eventually(expectation = nil, opts = nil, &block) 32 | ancestors = self.class.ancestors.map{|s| s.to_s} 33 | cls = if ancestors.include?('MiniTest::Unit::TestCase') 34 | Eventually::MiniTest 35 | elsif ancestors.include?('Test::Unit::TestCase') 36 | Eventually::TestUnit 37 | elsif self.class.to_s[/^RSpec::Core/] 38 | Eventually::RSpec 39 | else 40 | nil 41 | end 42 | cls.new(_pool, self, Callsite.parse(caller.first), expectation, opts, block) 43 | end 44 | alias_method :ly, :eventually 45 | 46 | def manually_stop_em! 47 | @_manually_stop_em = true 48 | end 49 | 50 | def parallel(&blk) 51 | _pool.in_parallel do 52 | instance_eval(&blk) 53 | end 54 | end 55 | 56 | def self.included(o) 57 | ancestors = o.ancestors.map{|s| s.to_s} 58 | cls = if ancestors.include?('MiniTest::Unit::TestCase') 59 | Eventually::MiniTest 60 | elsif ancestors.include?('Test::Unit::TestCase') 61 | Eventually::TestUnit 62 | elsif (o.respond_to?(:name) && o.name.to_s == 'RSpec::Core::ExampleGroup') || (o.respond_to?(:superclass) && o.superclass.to_s == 'RSpec::Core::ExampleGroup') 63 | Eventually::RSpec 64 | else 65 | raise("I know what testsuite i'm in!") 66 | end 67 | cls.inject 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/em-ventually/emify.rb: -------------------------------------------------------------------------------- 1 | module EventMachine 2 | module Ventually 3 | module Emify 4 | def _em 5 | result = nil 6 | if EM.reactor_running? 7 | result = yield 8 | else 9 | EM.run do 10 | begin 11 | result = yield 12 | ensure 13 | unless instance_variable_defined?(:@_manually_stop_em) && @_manually_stop_em 14 | EM.stop if (!instance_variable_defined?(:@_pool) || @_pool.nil? || @_pool.empty?) && EM.reactor_running? 15 | end 16 | end 17 | end 18 | end 19 | result 20 | end 21 | end 22 | end 23 | end -------------------------------------------------------------------------------- /lib/em-ventually/eventually.rb: -------------------------------------------------------------------------------- 1 | module EventMachine 2 | module Ventually 3 | class Eventually 4 | 5 | autoload :MiniTest, 'em-ventually/eventually/minitest' 6 | autoload :RSpec, 'em-ventually/eventually/rspec' 7 | autoload :TestUnit, 'em-ventually/eventually/testunit' 8 | 9 | attr_reader :expectation 10 | 11 | def initialize(pool, runner, caller, expectation, opts, block) 12 | @pool, @runner, @caller, @expectation, @opts, @block = pool, runner, caller, expectation, opts, block 13 | @count = 0 14 | @pool.push(self) 15 | @total_time = opts && opts[:total] || EventMachine::Ventually.total_default 16 | @every_time = opts && opts[:every] || EventMachine::Ventually.every_default 17 | @test_blk = expectation.nil? ? proc{|r| r } : proc{|r| expectation == r} 18 | @run_timer = EM.add_timer(0.05) { run } 19 | end 20 | 21 | def test(&blk) 22 | @test_blk = blk 23 | end 24 | 25 | def assert_test(got) 26 | @test_blk[got] 27 | end 28 | 29 | def formatted_message(msg) 30 | "#{msg} (#{@caller.filename}:#{@caller.line})" 31 | end 32 | 33 | def kill_timer 34 | @kill_timer ||= EM.add_timer(@total_time) { stop(formatted_message("Exceeded time#{", expected #{expectation.inspect}" unless expectation.nil?}, last value was #{@last_val.inspect}")) } 35 | end 36 | 37 | def run 38 | EM.cancel_timer(@run_timer) 39 | if @pool.should_run?(self) 40 | kill_timer 41 | if @block.arity != 1 42 | process_test(@last_val = @block.call) 43 | else 44 | @block[proc { |val| 45 | @last_val = val 46 | process_test(val) 47 | }] 48 | end 49 | else 50 | EM.add_timer(@every_time) { run } 51 | end 52 | end 53 | 54 | def process_test(val) 55 | if assert_test(val) 56 | stop 57 | else 58 | @count += 1 59 | EM.add_timer(@every_time) { run } 60 | end 61 | end 62 | 63 | def stop(msg = nil) 64 | EM.cancel_timer @kill_timer 65 | @pool.complete(self) 66 | report(msg) if msg 67 | if @pool.empty? && EM.reactor_running? 68 | EM.stop 69 | end 70 | end 71 | 72 | def report(msg) 73 | STDERR << "Msg: #{msg}\n" 74 | end 75 | end 76 | end 77 | end -------------------------------------------------------------------------------- /lib/em-ventually/eventually/minitest.rb: -------------------------------------------------------------------------------- 1 | module EventMachine 2 | module Ventually 3 | class Eventually 4 | class MiniTest < Eventually 5 | def self.inject 6 | unless ::MiniTest::Unit::TestCase.public_method_defined?(:_em) 7 | ::MiniTest::Unit::TestCase.class_eval <<-EOT, __FILE__, __LINE__ + 1 8 | include EM::Ventually::Emify 9 | alias_method :__original__send__, :__send__ 10 | old_warning_level = $VERBOSE 11 | $VERBOSE = nil 12 | def __send__(*args, &blk) 13 | if Callsite.parse(caller.first).method == 'run' 14 | _em { __original__send__(*args, &blk) } 15 | else 16 | __original__send__(*args, &blk) 17 | end 18 | end 19 | $VERBOSE = old_warning_level 20 | EOT 21 | end 22 | end 23 | 24 | def report(msg) 25 | @runner.assert false, msg 26 | end 27 | 28 | def assert_test(result) 29 | e = expectation 30 | if super 31 | msg = formatted_message("#{result.inspect} passed") 32 | @runner.instance_eval do 33 | assert true, msg 34 | end 35 | true 36 | else 37 | false 38 | end 39 | end 40 | end 41 | end 42 | end 43 | end -------------------------------------------------------------------------------- /lib/em-ventually/eventually/rspec.rb: -------------------------------------------------------------------------------- 1 | module EventMachine 2 | module Ventually 3 | class Eventually 4 | class RSpec < Eventually 5 | def self.inject 6 | unless ::RSpec::Core::ExampleGroup.public_method_defined?(:_em) 7 | ::RSpec::Core::ExampleGroup.class_eval <<-EOT, __FILE__, __LINE__ + 1 8 | include EM::Ventually::Emify 9 | alias_method :original_instance_eval, :instance_eval 10 | def instance_eval(&block) 11 | _em { original_instance_eval(&block) } 12 | end 13 | EOT 14 | end 15 | end 16 | 17 | def report(msg) 18 | ::RSpec::Expectations.fail_with(msg) 19 | end 20 | 21 | def assert_test(result) 22 | e = expectation 23 | if super 24 | msg = formatted_message("#{result.inspect} passed") 25 | @runner.instance_eval do 26 | 1.should == 1 27 | end 28 | true 29 | else 30 | false 31 | end 32 | end 33 | end 34 | end 35 | end 36 | end -------------------------------------------------------------------------------- /lib/em-ventually/eventually/testunit.rb: -------------------------------------------------------------------------------- 1 | module EventMachine 2 | module Ventually 3 | class Eventually 4 | class TestUnit < Eventually 5 | def self.inject 6 | unless ::Test::Unit::TestCase.public_method_defined?(:_em) 7 | ::Test::Unit::TestCase.class_eval <<-EOT, __FILE__, __LINE__ + 1 8 | include EM::Ventually::Emify 9 | alias_method :__original__send__, :__send__ 10 | old_warning_level = $VERBOSE 11 | $VERBOSE = nil 12 | def __send__(*args, &blk) 13 | if Callsite.parse(caller.first).method == 'run' 14 | _em { __original__send__(*args, &blk) } 15 | else 16 | __original__send__(*args, &blk) 17 | end 18 | end 19 | $VERBOSE = old_warning_level 20 | EOT 21 | end 22 | end 23 | 24 | def report(msg) 25 | @runner.assert false, msg 26 | end 27 | 28 | def assert_test(result) 29 | e = expectation 30 | if super 31 | msg = formatted_message("#{result.inspect} passed") 32 | @runner.instance_eval do 33 | assert true, msg 34 | end 35 | true 36 | else 37 | false 38 | end 39 | end 40 | end 41 | end 42 | end 43 | end -------------------------------------------------------------------------------- /lib/em-ventually/minitest.rb: -------------------------------------------------------------------------------- 1 | require 'em-ventually' 2 | 3 | MiniTest::Unit::TestCase.class_eval do 4 | include EM::Ventually 5 | end 6 | -------------------------------------------------------------------------------- /lib/em-ventually/pool.rb: -------------------------------------------------------------------------------- 1 | module EventMachine 2 | module Ventually 3 | class Pool 4 | def initialize 5 | @store = [] 6 | end 7 | 8 | def should_run?(eventually) 9 | case @store.first 10 | when Array 11 | @store.first.include?(eventually) 12 | else 13 | @store.first == eventually 14 | end 15 | end 16 | 17 | def in_parallel 18 | @store.push [] 19 | yield 20 | end 21 | 22 | def push(e) 23 | if @store.last.is_a?(Array) 24 | @store.last.last.run unless @store.last.last.nil? 25 | @store.last.push(e) 26 | else 27 | @store.last.run unless @store.last.nil? 28 | @store.push(e) 29 | end 30 | end 31 | 32 | def complete(e) 33 | if @store.first.is_a?(Array) 34 | @store.first.delete(e) 35 | @store.shift if @store.last.empty? 36 | else 37 | @store.delete(e) 38 | end 39 | end 40 | 41 | def empty? 42 | @store.empty? 43 | end 44 | end 45 | end 46 | end -------------------------------------------------------------------------------- /lib/em-ventually/rspec.rb: -------------------------------------------------------------------------------- 1 | require 'em-ventually' 2 | 3 | RSpec::Core::ExampleGroup.class_eval do 4 | include EM::Ventually 5 | end -------------------------------------------------------------------------------- /lib/em-ventually/testunit.rb: -------------------------------------------------------------------------------- 1 | require 'em-ventually' 2 | 3 | Test::Unit::TestCase.class_eval do 4 | include EM::Ventually 5 | end 6 | -------------------------------------------------------------------------------- /lib/em-ventually/version.rb: -------------------------------------------------------------------------------- 1 | module EventMachine 2 | module Ventually 3 | VERSION = "0.1.3" 4 | end 5 | end -------------------------------------------------------------------------------- /test/minitest-2.0/Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | gem 'minitest', '~> 2.0.0' 4 | gem 'eventmachine' 5 | gem 'rake', '0.8.7' 6 | gem 'phocus' 7 | gem 'callsite' -------------------------------------------------------------------------------- /test/minitest-2.0/Rakefile: -------------------------------------------------------------------------------- 1 | task :default => :test 2 | 3 | desc "Run tests" 4 | task :test do 5 | $: << File.expand_path("#{File.dirname(__FILE__)}/../../lib") 6 | require 'em-ventually' 7 | require './helper' 8 | Dir['./*.rb'].each { |test| require test } 9 | end 10 | -------------------------------------------------------------------------------- /test/minitest-2.0/helper.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'phocus' 3 | -------------------------------------------------------------------------------- /test/minitest-2.0/test_ventually.rb: -------------------------------------------------------------------------------- 1 | class TestMounting < MiniTest::Unit::TestCase 2 | include EM::Ventually 3 | 4 | def test_simple 5 | assert_equal 1, 1 6 | end 7 | 8 | def test_em_simple 9 | val = nil 10 | EM.add_timer(0.5) { val = 'test' } 11 | eventually('test') { val } 12 | end 13 | 14 | def test_em_passing 15 | val = nil 16 | EM.add_timer(0.5) { val = 'test' } 17 | eventually('test') {|m| m[val] } 18 | end 19 | 20 | def test_multiple 21 | val = nil 22 | EM.add_timer(0.3) { val = 'test' } 23 | EM.add_timer(0.8) { val = 'test2' } 24 | eventually('test') {|m| m[val] } 25 | eventually('test2') {|m| m[val] } 26 | end 27 | 28 | def test_out_of_order # this should fail 29 | val = nil 30 | EM.add_timer(0.3) { val = 'test2' } 31 | EM.add_timer(0.8) { val = 'test' } 32 | eventually('test') {|m| m[val] } 33 | eventually('test2') {|m| m[val] } 34 | end 35 | 36 | def test_out_of_order_with_parallel 37 | val = nil 38 | EM.add_timer(0.3) { val = 'test2' } 39 | EM.add_timer(0.8) { val = 'test' } 40 | parallel { 41 | eventually('test') {|m| m[val] } 42 | eventually('test2') {|m| m[val] } 43 | } 44 | end 45 | end -------------------------------------------------------------------------------- /test/rspec-2.6/Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | gem 'rspec', '~> 2.6.0' 4 | gem 'eventmachine' 5 | gem 'rake', '0.8.7' 6 | gem 'callsite' -------------------------------------------------------------------------------- /test/rspec-2.6/Rakefile: -------------------------------------------------------------------------------- 1 | task :default => :spec 2 | 3 | require 'rspec/core/rake_task' 4 | RSpec::Core::RakeTask.new(:spec) { |spec| 5 | spec.pattern = "*_spec.rb" 6 | } 7 | -------------------------------------------------------------------------------- /test/rspec-2.6/helper.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | -------------------------------------------------------------------------------- /test/rspec-2.6/ventually_spec.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH << "#{File.dirname(__FILE__)}/../../lib" 2 | require 'em-ventually/rspec' 3 | 4 | describe EM::Ventually do 5 | 6 | it "should allow a normal test" do 7 | 1.should == 1 8 | end 9 | 10 | it "should allow a simple em test" do 11 | val = nil 12 | EM.add_timer(0.5) { val = 'test' } 13 | eventually('test') { val } 14 | end 15 | 16 | it "should allow an em test with value passing" do 17 | val = nil 18 | EM.add_timer(0.5) { val = 'test' } 19 | eventually('test') {|m| m[val] } 20 | end 21 | 22 | it "should allow multiple eventuallys" do 23 | val = nil 24 | EM.add_timer(0.3) { val = 'test' } 25 | EM.add_timer(0.8) { val = 'test2' } 26 | eventually('test') {|m| m[val] } 27 | eventually('test2') {|m| m[val] } 28 | end 29 | 30 | it "should fail when out of order" do 31 | val = nil 32 | EM.add_timer(0.3) { val = 'test2' } 33 | EM.add_timer(0.8) { val = 'test' } 34 | eventually('test') {|m| m[val] } 35 | eventually('test2') {|m| m[val] } 36 | end 37 | 38 | it "should succeed when out of order using parallel" do 39 | val = nil 40 | EM.add_timer(0.3) { val = 'test2' } 41 | EM.add_timer(0.8) { val = 'test' } 42 | parallel { 43 | eventually('test') {|m| m[val] } 44 | eventually('test2') {|m| m[val] } 45 | } 46 | end 47 | 48 | it "should allow longer tests with a specific number of passes" do 49 | val = nil 50 | count = 0 51 | EM.add_timer(3.1) { val = 'done'} 52 | eventually('done', :every => 0.5, :total => 3.5) { count +=1; val } 53 | eventually(7) { count } 54 | end 55 | 56 | it "should allow custom tests" do 57 | val = nil 58 | count = 0 59 | time = Time.new.to_f 60 | EM.add_timer(0.5) { val = 'done'} 61 | eventually('done') { val } 62 | eventually { Time.new.to_f - time }.test{|t| t < 1} 63 | end 64 | end -------------------------------------------------------------------------------- /test/test-unit/Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | gem 'eventmachine' 4 | gem 'rake', '0.8.7' 5 | gem 'phocus' 6 | gem 'callsite' -------------------------------------------------------------------------------- /test/test-unit/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | desc "Run basic tests" 4 | Rake::TestTask.new("test") { |t| 5 | t.pattern = File.expand_path("#{File.dirname(__FILE__)}/test_*.rb") 6 | t.verbose = true 7 | t.warning = true 8 | t.libs = [File.expand_path("#{File.dirname(__FILE__)}/../../lib")] 9 | } 10 | 11 | task :default => :test -------------------------------------------------------------------------------- /test/test-unit/helper.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'phocus' 3 | -------------------------------------------------------------------------------- /test/test-unit/test_ventually.rb: -------------------------------------------------------------------------------- 1 | require 'em-ventually' 2 | require 'test/unit' 3 | 4 | class TestEMVentually < Test::Unit::TestCase 5 | include EM::Ventually 6 | 7 | def test_simple 8 | assert_equal 1, 1 9 | end 10 | 11 | def test_em_simple 12 | val = nil 13 | EM.add_timer(0.5) { val = 'test' } 14 | eventually('test') { val } 15 | end 16 | 17 | def test_em_passing 18 | val = nil 19 | EM.add_timer(0.5) { val = 'test' } 20 | eventually('test') {|m| m[val] } 21 | end 22 | 23 | def test_multiple 24 | val = nil 25 | EM.add_timer(0.3) { val = 'test' } 26 | EM.add_timer(0.8) { val = 'test2' } 27 | eventually('test') {|m| m[val] } 28 | eventually('test2') {|m| m[val] } 29 | end 30 | 31 | def test_out_of_order # this should fail 32 | val = nil 33 | EM.add_timer(0.3) { val = 'test2' } 34 | EM.add_timer(0.8) { val = 'test' } 35 | eventually('test') {|m| m[val] } 36 | eventually('test2') {|m| m[val] } 37 | end 38 | 39 | def test_out_of_order_with_parallel 40 | val = nil 41 | EM.add_timer(0.3) { val = 'test2' } 42 | EM.add_timer(0.8) { val = 'test' } 43 | parallel { 44 | eventually('test') {|m| m[val] } 45 | eventually('test2') {|m| m[val] } 46 | } 47 | end 48 | end --------------------------------------------------------------------------------