em-spec-0.2.7/0000755000004100000410000000000012677056065013117 5ustar www-datawww-dataem-spec-0.2.7/Rakefile0000644000004100000410000000061512677056065014566 0ustar www-datawww-datarequire '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 em-spec-0.2.7/Gemfile.lock0000644000004100000410000000142412677056065015342 0ustar www-datawww-dataPATH remote: . specs: em-spec (0.2.7) eventmachine GEM remote: http://rubygems.org/ specs: bacon (1.1.0) diff-lcs (1.1.3) eventmachine (1.0.9.1) 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 bacon em-spec! growl guard-bundler guard-rspec rake (= 0.8.7) rspec (> 2.6.0) test-unit BUNDLED WITH 1.10.6 em-spec-0.2.7/Gemfile0000644000004100000410000000013312677056065014407 0ustar www-datawww-datasource "http://rubygems.org" # Specify your gem's dependencies in em-spec.gemspec gemspec em-spec-0.2.7/em-spec.gemspec0000644000004100000410000000256512677056065016025 0ustar www-datawww-data# -*- 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.files = `git ls-files`.split("\n") s.homepage = %q{https://github.com/joshbuddy/em-spec} 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' s.add_dependency 'eventmachine' # These are not runtime dependencies since in most cases people will use # em-spec with only one of these libraries s.add_development_dependency 'rspec', '> 2.6.0' s.add_development_dependency 'bacon' s.add_development_dependency 'test-unit' 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 em-spec-0.2.7/.rspec0000644000004100000410000000001012677056065014223 0ustar www-datawww-data--colourem-spec-0.2.7/spec/0000755000004100000410000000000012677056065014051 5ustar www-datawww-dataem-spec-0.2.7/spec/rspec_fail_examples.rb0000644000004100000410000000054212677056065020404 0ustar www-datawww-datarequire 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 endem-spec-0.2.7/spec/rspec_spec.rb0000644000004100000410000000327512677056065016533 0ustar www-datawww-datarequire 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 endem-spec-0.2.7/lib/0000755000004100000410000000000012677056065013665 5ustar www-datawww-dataem-spec-0.2.7/lib/em-spec/0000755000004100000410000000000012677056065015216 5ustar www-datawww-dataem-spec-0.2.7/lib/em-spec/bacon.rb0000644000004100000410000000400312677056065016622 0ustar www-datawww-datarequire 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 endem-spec-0.2.7/lib/em-spec/test.rb0000644000004100000410000000445112677056065016526 0ustar www-datawww-datarequire '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 defined? @_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 em-spec-0.2.7/lib/em-spec/version.rb0000644000004100000410000000010212677056065017221 0ustar www-datawww-datamodule EventMachine module Spec VERSION = '0.2.7' end end em-spec-0.2.7/lib/em-spec/rspec.rb0000644000004100000410000000262512677056065016664 0ustar www-datawww-datarequire '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 em-spec-0.2.7/lib/ext/0000755000004100000410000000000012677056065014465 5ustar www-datawww-dataem-spec-0.2.7/lib/ext/fiber18.rb0000644000004100000410000000312512677056065016253 0ustar www-datawww-data# 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 em-spec-0.2.7/test/0000755000004100000410000000000012677056065014076 5ustar www-datawww-dataem-spec-0.2.7/test/bacon_spec.rb0000644000004100000410000000274712677056065016531 0ustar www-datawww-datarequire '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 endem-spec-0.2.7/test/test_spec.rb0000644000004100000410000000257212677056065016422 0ustar www-datawww-data$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 endem-spec-0.2.7/.gitignore0000644000004100000410000000001212677056065015100 0ustar www-datawww-data*.gem pkg em-spec-0.2.7/LICENSE0000644000004100000410000000206512677056065014127 0ustar www-datawww-dataThe MIT License (MIT) Copyright (c) 2016 @joshbuddy 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. em-spec-0.2.7/CHANGELOG.md0000644000004100000410000000006112677056065014725 0ustar www-datawww-data## 0.2.7 Added MIT license, on popular request. em-spec-0.2.7/README.md0000644000004100000410000000602412677056065014400 0ustar www-datawww-data# Simple BDD API for testing asynchronous Ruby/EventMachine code `em-spec` can be used with either bacon, test unit or rspec. ## Rspec There are two ways to use with the Rspec gem. 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. ```ruby 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: ```ruby 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: ```ruby 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. ```ruby 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: ```ruby 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 * [Bacon](http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/30b07b651b0662fd) em-spec-0.2.7/Guardfile0000644000004100000410000000024012677056065014740 0ustar www-datawww-dataguard 'bundler' do watch(/^Gemfile/) watch(/^.+\.gemspec/) end guard 'rspec', :version => 2 do watch(/^spec\/.*_spec\.rb/) watch(/^lib\/(.*)\.rb/) end