pax_global_header00006660000000000000000000000064121227036650014516gustar00rootroot0000000000000052 comment=fe03a95401d0de33c0544c45a29a7892bee27743 ruby-em-spec-0.2.6/000077500000000000000000000000001212270366500140335ustar00rootroot00000000000000ruby-em-spec-0.2.6/.gitignore000066400000000000000000000000121212270366500160140ustar00rootroot00000000000000*.gem pkg ruby-em-spec-0.2.6/.rspec000066400000000000000000000000101212270366500151370ustar00rootroot00000000000000--colourruby-em-spec-0.2.6/Gemfile000066400000000000000000000001331212270366500153230ustar00rootroot00000000000000source "http://rubygems.org" # Specify your gem's dependencies in em-spec.gemspec gemspec ruby-em-spec-0.2.6/Gemfile.lock000066400000000000000000000014101212270366500162510ustar00rootroot00000000000000PATH remote: . specs: em-spec (0.2.6) bacon eventmachine rspec (> 2.6.0) test-unit GEM remote: http://rubygems.org/ specs: bacon (1.1.0) diff-lcs (1.1.3) eventmachine (0.12.10) growl (1.0.3) guard (0.8.8) thor (~> 0.14.6) guard-bundler (0.1.3) bundler (>= 1.0.0) guard (>= 0.2.2) guard-rspec (0.5.9) guard (>= 0.8.4) rake (0.8.7) rspec (2.7.0) rspec-core (~> 2.7.0) rspec-expectations (~> 2.7.0) rspec-mocks (~> 2.7.0) rspec-core (2.7.1) rspec-expectations (2.7.0) diff-lcs (~> 1.1.2) rspec-mocks (2.7.0) test-unit (2.4.2) thor (0.14.6) PLATFORMS ruby DEPENDENCIES em-spec! growl guard-bundler guard-rspec rake (= 0.8.7) ruby-em-spec-0.2.6/Guardfile000066400000000000000000000002401212270366500156540ustar00rootroot00000000000000guard 'bundler' do watch(/^Gemfile/) watch(/^.+\.gemspec/) end guard 'rspec', :version => 2 do watch(/^spec\/.*_spec\.rb/) watch(/^lib\/(.*)\.rb/) end ruby-em-spec-0.2.6/README.rdoc000066400000000000000000000061571212270366500156520ustar00rootroot00000000000000Simple BDD API for testing asynchronous Ruby/EventMachine code (c) 2008 Aman Gupta (tmm1) em-spec can be used with either bacon, test unit or rspec. =Rspec There are two ways to use the Rspec extension. To use it as a helper, include EM::SpecHelper in your describe block. You then use the em method to wrap your evented test code. Inside the em block, you must call #done after your expectations. Everything works normally otherwise. require "em-spec/rspec" describe EventMachine do include EM::SpecHelper it "works normally when not using #em" do 1.should == 1 end it "makes testing evented code easy with #em" do em do start = Time.now EM.add_timer(0.5){ (Time.now-start).should be_close( 0.5, 0.1 ) done } end end end The other option is to include EM::Spec in your describe block. This will patch Rspec so that all of your examples run inside an em block automatically: require "em-spec/rspec" describe EventMachine do include EM::Spec it "requires a call to #done every time" do 1.should == 1 done end it "runs test code in an em block automatically" do start = Time.now EM.add_timer(0.5){ (Time.now-start).should be_close( 0.5, 0.1 ) done } end end =Bacon The API is identical to Bacon, except that you must explicitly call 'done' after all the current behavior's assertions have been made: require 'em-spec/bacon' EM.describe EventMachine do should 'have timers' do start = Time.now EM.add_timer(0.5){ (Time.now-start).should.be.close 0.5, 0.1 done } end should 'have periodic timers' do num = 0 start = Time.now timer = EM.add_periodic_timer(0.5){ if (num += 1) == 2 (Time.now-start).should.be.close 1.0, 0.1 EM.__send__ :cancel_timer, timer done end } end end =Test::Unit There are two ways to use the Test::Unit extension. To use it as a helper, include EM::TestHelper in your test unit class. You then use the em method to wrap your evented test code. Inside the em block, you must call #done after your expectations. Everything works normally otherwise. require 'em-spec/test' class EmSpecHelperTest < Test::Unit::TestCase include EventMachine::TestHelper def test_trivial em do assert_equal 1, 1 done end end end The other option is to include EM::Test in your test class. This will patch Test::Unit so that all of your examples run inside an em block automatically: require 'em-spec/test' class EmSpecTest < Test::Unit::TestCase include EventMachine::Test def test_timer start = Time.now EM.add_timer(0.5){ assert_in_delta 0.5, Time.now-start, 0.1 done } end end Resources: * Git repository: http://github.com/tmm1/em-spec * Bacon: http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/30b07b651b0662fd * Initial announcement: http://groups.google.com/group/eventmachine/browse_thread/thread/8b4e7ead72f9d013 ruby-em-spec-0.2.6/Rakefile000066400000000000000000000006151212270366500155020ustar00rootroot00000000000000require 'rake/testtask' require 'rubygems' require 'bundler' Bundler::GemHelper.install_tasks task :default => :spec Rake::TestTask.new do |t| t.libs << "test" t.test_files = FileList['test/test_spec.rb'] t.verbose = true end task :spec do sh('rake test') rescue nil sh('bacon test/bacon_spec.rb') rescue nil sh 'spec -f specdoc test/rspec_spec.rb test/rspec_fail_examples.rb' end ruby-em-spec-0.2.6/em-spec.gemspec000066400000000000000000000024671212270366500167420ustar00rootroot00000000000000# -*- encoding: utf-8 -*- require File.join(File.dirname(__FILE__), 'lib', 'em-spec', 'version') Gem::Specification.new do |s| s.name = 'em-spec' s.version = EventMachine::Spec::VERSION s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Aman Gupta", "Julien Ammous"] s.summary = "BDD for Ruby/EventMachine" s.description = "Simple BDD API for testing asynchronous Ruby/EventMachine code" s.email = %q{schmurfy@gmail.com} s.extra_rdoc_files = ['README.rdoc'] s.files = `git ls-files`.split("\n") s.homepage = %q{http://github.com/schmurfy/em-spec} s.rdoc_options = ["--charset=UTF-8"] s.require_paths = ["lib"] s.rubygems_version = %q{1.3.7} s.test_files = `git ls-files`.split("\n").select{|f| f =~ /^test/} s.rubyforge_project = 'em-spec' # dependencies s.add_dependency 'rspec', '> 2.6.0' s.add_dependency 'bacon' s.add_dependency 'test-unit' s.add_dependency 'eventmachine' if RUBY_PLATFORM.downcase.include?("darwin") # also install growlnotify from the # Extras/growlnotify/growlnotify.pkg in Growl disk image s.add_development_dependency 'growl' end s.add_development_dependency 'guard-rspec' s.add_development_dependency 'guard-bundler' s.add_development_dependency 'rake', '= 0.8.7' end ruby-em-spec-0.2.6/lib/000077500000000000000000000000001212270366500146015ustar00rootroot00000000000000ruby-em-spec-0.2.6/lib/em-spec/000077500000000000000000000000001212270366500161325ustar00rootroot00000000000000ruby-em-spec-0.2.6/lib/em-spec/bacon.rb000066400000000000000000000040031212270366500175360ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../ext/fiber18' require 'rubygems' require 'eventmachine' module EventMachine def self.spec_backend=( backend ) @spec_backend = backend end def self.spec_backend @spec_backend end def self.spec *args, &blk raise ArgumentError, 'block required' unless block_given? raise 'EventMachine reactor already running' if EM.reactor_running? spec_backend.spec( args, blk ) end class << self; alias :describe :spec; end def self.bacon( *args, &block ) require File.dirname(__FILE__) + '/spec/bacon' self.spec_backend = EventMachine::Spec::Bacon self.spec( args, &block ) end end module EventMachine module Spec module Bacon def self.spec( args, blk ) EM.run do ::Bacon.summary_on_exit ($em_spec_fiber = Fiber.new{ ::Bacon::FiberedContext.new(args.join(' '), &blk).run EM.stop_event_loop }).resume end end end end end class Bacon::FiberedContext < Bacon::Context SpecTimeoutExceededError = Class.new(RuntimeError) def default_timeout(timeout) $_em_default_time_to_finish = timeout end def cancel_timer EM.cancel_timer($_em_timer) if $_em_timer end def timeout(time_to_run) cancel_timer $_em_timer = EM.add_timer(time_to_run) { done(false) } end def it *args super{ if block_given? if $_em_default_time_to_finish timeout($_em_default_time_to_finish) end yield Fiber.yield end } end def describe(*args, &block) context = Bacon::FiberedContext.new(args.join(' '), &block) @before.each { |b| context.before(&b) } @after.each { |b| context.after(&b) } context.run end def done(succeed = true) cancel_timer EM.next_tick{ if succeed :done.should == :done else should.flunk end $em_spec_fiber.resume if $em_spec_fiber } end endruby-em-spec-0.2.6/lib/em-spec/rspec.rb000066400000000000000000000026251212270366500176000ustar00rootroot00000000000000require 'eventmachine' require File.dirname(__FILE__) + '/../ext/fiber18' module EventMachine module SpecHelper SpecTimeoutExceededError = Class.new(RuntimeError) def self.included(cls) ::RSpec::Core::ExampleGroup.instance_eval " @@_em_default_time_to_finish = nil def self.default_timeout(timeout) @@_em_default_time_to_finish = timeout end " end def timeout(time_to_run) EM.cancel_timer(@_em_timer) if @_em_timer @_em_timer = EM.add_timer(time_to_run) { done; raise SpecTimeoutExceededError.new } end def em(time_to_run = @@_em_default_time_to_finish, &block) em_spec_exception = nil EM.run do timeout(time_to_run) if time_to_run @_em_spec_fiber = Fiber.new do begin block.call rescue Exception => em_spec_exception done end Fiber.yield end @_em_spec_fiber.resume end raise em_spec_exception if em_spec_exception end def done EM.next_tick{ finish_em_spec_fiber } end private def finish_em_spec_fiber EM.stop_event_loop if EM.reactor_running? @_em_spec_fiber.resume if @_em_spec_fiber.alive? end end module Spec include SpecHelper def instance_eval(&block) em do super(&block) end end end end ruby-em-spec-0.2.6/lib/em-spec/test.rb000066400000000000000000000044401212270366500174400ustar00rootroot00000000000000require 'eventmachine' require File.dirname(__FILE__) + '/../ext/fiber18' module EventMachine TestTimeoutExceededError = Class.new(RuntimeError) module TestHelper def self.included(cls) cls.class_eval(<<-HERE_DOC, __FILE__, __LINE__) DefaultTimeout = nil unless const_defined?(:DefaultTimeout) def self.default_timeout(timeout) if self.const_defined? :DefaultTimeout self.ancestors.each do |cls| begin cls.send(:remove_const, :DefaultTimeout) cls.send(:const_set, :DefaultTimeout, timeout) break rescue end end else self.send(:const_set, :DefaultTimeout, timeout) end end def current_default_timeout DefaultTimeout end HERE_DOC end def timeout(time_to_run) EM.cancel_timer(@_em_timer) if @_em_timer @_em_timer = EM.add_timer(time_to_run) { done('timeout exceeded') } end def em(time_to_run = current_default_timeout, &block) @flunk_test = nil EM.run do timeout(time_to_run) if time_to_run em_spec_exception = nil @_em_spec_fiber = Fiber.new do @_output = begin block.call rescue Exception => em_spec_exception done end Fiber.yield end @_em_spec_fiber.resume raise em_spec_exception if em_spec_exception end raise(@flunk_test) if @flunk_test @_output end def done(flunk_reason = nil) EM.next_tick { @flunk_test = flunk_reason finish_em_spec_fiber } end private def finish_em_spec_fiber EM.stop_event_loop if EM.reactor_running? @_em_spec_fiber.resume if @_em_spec_fiber.alive? end end module Test def self.included(cls) cls.class_eval(<<-HERE_DOC, __FILE__, __LINE__) include TestHelper alias_method :run_without_em, :run def run(result, &block) em(DefaultTimeout) { run_without_em(result, &block) } rescue Exception => e if RUBY_VERSION >= "1.9.1" result.puke(self.class, @name, e) else add_error($!) end end HERE_DOC end end end ruby-em-spec-0.2.6/lib/em-spec/version.rb000066400000000000000000000001021212270366500201350ustar00rootroot00000000000000module EventMachine module Spec VERSION = '0.2.6' end end ruby-em-spec-0.2.6/lib/ext/000077500000000000000000000000001212270366500154015ustar00rootroot00000000000000ruby-em-spec-0.2.6/lib/ext/fiber18.rb000066400000000000000000000031251212270366500171670ustar00rootroot00000000000000# Poor Man's Fiber (API compatible Thread based Fiber implementation for Ruby 1.8) # (c) 2008 Aman Gupta (tmm1) unless defined? Fiber require 'thread' class FiberError < StandardError; end class Fiber def initialize raise ArgumentError, 'new Fiber requires a block' unless block_given? @yield = Queue.new @resume = Queue.new @thread = Thread.new{ @yield.push [ *yield(*@resume.pop) ] } @thread.abort_on_exception = true @thread[:fiber] = self end attr_reader :thread def alive? @thread.alive? end def resume *args raise FiberError, 'dead fiber called' unless @thread.alive? raise FiberError, 'double resume' if @thread == Thread.current @resume.push(args) result = @yield.pop result.size > 1 ? result : result.first end def resume! @resume.push [] end def yield *args @yield.push(args) result = @resume.pop result.size > 1 ? result : result.first end def self.yield *args raise FiberError, "can't yield from root fiber" unless fiber = Thread.current[:fiber] fiber.yield(*args) end def self.current Thread.current[:fiber] or raise FiberError, 'not inside a fiber' end def inspect "#<#{self.class}:0x#{self.object_id.to_s(16)}>" end end else require 'fiber' unless Fiber.respond_to?(:current) end if __FILE__ == $0 f = Fiber.new{ puts 'hi'; p Fiber.yield(1); puts 'bye'; :done } p f.resume p f.resume(2) end __END__ $ ruby fbr.rb hi 1 2 bye :done $ ruby1.9 fbr.rb hi 1 2 bye :done ruby-em-spec-0.2.6/spec/000077500000000000000000000000001212270366500147655ustar00rootroot00000000000000ruby-em-spec-0.2.6/spec/rspec_fail_examples.rb000066400000000000000000000005421212270366500213200ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../lib/em-spec/rspec' describe EventMachine, "when running failing examples" do include EM::Spec it "should not bubble failures beyond rspec" do EM.add_timer(0.1) do :should_not_bubble.should == :failures done end end it "should not block on failure" do 1.should == 2 end endruby-em-spec-0.2.6/spec/rspec_spec.rb000066400000000000000000000032751212270366500174470ustar00rootroot00000000000000require File.dirname(__FILE__) + '/../lib/em-spec/rspec' describe 'Rspec' do it 'should work as normal outside EM.describe' do 1.should == 1 end end describe EventMachine, "when testing with EM::SpecHelper" do include EM::SpecHelper it "should not require a call to done when #em is not used" do 1.should == 1 end it "should have timers" do em do start = Time.now EM.add_timer(0.5) { (Time.now - start).should be_within(0.1).of(0.5) done } end end end describe EventMachine, "when testing with EM::Spec" do include EM::Spec it 'should work' do done end it 'should have timers' do start = Time.now EM.add_timer(0.5) { (Time.now - start).should be_within(0.5).of(0.5) done } end it 'should have periodic timers' do num = 0 start = Time.now timer = EM.add_periodic_timer(0.5) { if (num += 1) == 2 (Time.now - start).should be_within(1).of(0.5) EM.__send__ :cancel_timer, timer done end } end it 'should have deferrables' do defr = EM::DefaultDeferrable.new defr.timeout(1) defr.errback{ done } end end describe EventMachine, "when testing with EM::Spec with a maximum execution time per test" do include EM::Spec default_timeout 4 it 'should timeout before reaching done' do EM.add_timer(3) { done } end it 'should timeout before reaching done' do timeout(4) EM.add_timer(3) { done } end end describe "Rspec", "when running an example group after another group that uses EMSpec " do it "should work normally" do :does_not_hang.should_not be_false end endruby-em-spec-0.2.6/test/000077500000000000000000000000001212270366500150125ustar00rootroot00000000000000ruby-em-spec-0.2.6/test/bacon_spec.rb000066400000000000000000000027471212270366500174450ustar00rootroot00000000000000require 'bacon' require File.dirname(__FILE__) + '/../lib/em-spec/bacon' EM.spec_backend = EventMachine::Spec::Bacon describe 'Bacon' do should 'work as normal outside EM.describe' do 1.should == 1 end end EM.describe EventMachine do should 'work' do done end should 'have timers' do start = Time.now EM.add_timer(0.5){ (Time.now-start).should.be.close 0.5, 0.1 done } end should 'have periodic timers' do num = 0 start = Time.now timer = EM.add_periodic_timer(0.5){ if (num += 1) == 2 (Time.now-start).should.be.close 1.0, 0.1 EM.__send__ :cancel_timer, timer done end } end should 'have deferrables' do defr = EM::DefaultDeferrable.new defr.timeout(1) defr.errback{ done } end describe 'subscope' do should 'works here' do i_did_it = false fib = Fiber.current EM.add_timer(0.1){ i_did_it = true fib.resume } Fiber.yield i_did_it.should == true proc{ done }.should.not.raise(NameError) end end # it "should not block on failure" do # 1.should == 2 # end end EM.describe EventMachine, "with time restrictions" do default_timeout 2 should 'succeed here' do timeout(5) EM.add_timer(3) { done } end end EM.describe EventMachine, "with time restrictions" do default_timeout 2 should 'raise fail here' do EM.add_timer(3) { done } end endruby-em-spec-0.2.6/test/test_spec.rb000066400000000000000000000025721212270366500173360ustar00rootroot00000000000000$LOAD_PATH.unshift "lib" require 'test/unit' require 'rubygems' require 'eventmachine' require 'em-spec/test' class NormalTest < Test::Unit::TestCase def test_trivial assert_equal 1, 1 end end class EmSpecHelperTest < Test::Unit::TestCase include EventMachine::TestHelper def test_trivial em do assert_equal 1, 1 done end end def test_timer em do start = Time.now EM.add_timer(0.5){ assert_in_delta 0.5, Time.now-start, 0.1 done } end end end class EmSpecTest < Test::Unit::TestCase include EventMachine::Test def test_working done end def test_timer start = Time.now EM.add_timer(0.5){ assert_in_delta 0.5, Time.now-start, 0.1 done } end def test_deferrable defr = EM::DefaultDeferrable.new defr.timeout(1) defr.errback{ done } end end class EmSpecWithTimeoutTest < Test::Unit::TestCase include EventMachine::Test default_timeout 2 def test_should_fail_to_timeout EM.add_timer(3) { done } end end class EmSpecWithTimeoutOverrideTest < Test::Unit::TestCase include EventMachine::Test default_timeout 2 def test_timeout_override timeout(4) EM.add_timer(3) { done } end end class AnotherNormalTest < Test::Unit::TestCase def test_normal assert_equal 1, 1 end end