em-ventually 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -5,11 +5,28 @@
5
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
6
 
7
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:
8
9
 
9
10
  ~~~~~ {ruby}
10
- def test_em_simple1
11
- val = nil
12
- EM.add_timer(0.5) { val = 'test' }
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
13
30
  end
14
31
  ~~~~~
15
32
 
@@ -22,17 +39,27 @@ So, you want to test that val is 'test', and as well, you want EM to start on th
22
39
  Taking the example above you can enqueue a test.
23
40
 
24
41
  ~~~~~ {ruby}
25
- def test_em_simple2
26
- val = nil
42
+ def test_em
43
+ val = 'not test'
27
44
  EM.add_timer(0.5) { val = 'test' }
28
45
  eventually('test') { val }
29
46
  end
30
47
  ~~~~~
31
48
 
32
- This will poll your block every 0.1 seconds to see if the condition is true. After one second, if it's still not true, it will fail. You can mess with both values by passing in `:every` and `:total`. For example:
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:
33
60
 
34
61
  ~~~~~ {ruby}
35
- def test_em_simple3
62
+ def test_em
36
63
  val = nil
37
64
  EM.add_timer(0.5) { val = 'test' }
38
65
  eventually('test', :every => 0.2, :total => 10) { val } # check every 0.2 seconds
@@ -43,7 +70,7 @@ This will poll your block every 0.1 seconds to see if the condition is true. Aft
43
70
  You can also parallelize tests if you don't want them to run serially.
44
71
 
45
72
  ~~~~~ {ruby}
46
- def test_em_simple4
73
+ def test_em
47
74
  val1, val2 = nil, nil
48
75
  EM.add_timer(0.5) { val1 = 'test1' }
49
76
  EM.add_timer(0.5) { val2 = 'test2' }
@@ -54,14 +81,21 @@ You can also parallelize tests if you don't want them to run serially.
54
81
  end
55
82
  ~~~~~
56
83
 
57
- As well, simple returning doesn't always cover your test. You can pass values back for equality by doing the following.
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.
58
85
 
59
86
  ~~~~~ {ruby}
60
- def test_em_simple5
61
- val = nil
62
- EM.add_timer(0.5) { val = 'test1' }
63
- eventually('test1') { |with| with[val] } # The secret sauce is if you called
64
- # `eventually` with a block that takes a parameter or not.
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`
65
99
  end
66
100
  ~~~~~
67
101
 
@@ -74,7 +108,7 @@ There are a couple of global options you can mess with too. `EM::Ventually.every
74
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.
75
109
 
76
110
  ~~~~~ {ruby}
77
- def test_em_with_test6
111
+ def test_em
78
112
  count = 0
79
113
  EM.add_periodic_timer(0.01) { count += 0.5 }
80
114
  eventually { count }.test{ |v| v >= 3 }
@@ -84,9 +118,18 @@ If you don't pass a value to eventually, it will test that your value is true (i
84
118
  of course, you're gonna be writing so many of these we've aliased it to make your tests stylish and classy.
85
119
 
86
120
  ~~~~~ {ruby}
87
- def test_em_with_test6
121
+ def test_em
88
122
  count = 0
89
123
  EM.add_periodic_timer(0.01) { count += 0.5 }
90
124
  ly { count }.test{ |v| v >= 3 }
91
125
  end
92
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
+ ~~~~~
data/Rakefile CHANGED
@@ -1,45 +1,60 @@
1
1
  require 'bundler/gem_tasks'
2
2
 
3
3
  task :default => :test
4
+ task :test => [:'test:readme', :'test:suites']
4
5
 
5
- task :test do
6
- matchers = {
7
- 'minitest-2.0' => [/6 tests, 9 assertions, 1 failures, 0 errors, 0 skips/m],
8
- 'rspec-2.6' => [/\n\.\.\.\.F\.\.\.\n/m],
9
- 'test-unit' => [/\n\.\.\.F\.\.\n/m, /test_out_of_order\(TestEMVentually\)/m]
10
- }
6
+ namespace :test do
7
+ task :suites do
8
+ matchers = {
9
+ 'minitest-2.0' => [/6 tests, 9 assertions, 1 failures, 0 errors/m],
10
+ 'rspec-2.6' => [/\n\.\.\.\.F\.\.\.\n/m],
11
+ 'test-unit' => [/\n\.\.\.F\.\.\n/m, /test_out_of_order\(TestEMVentually\)/m]
12
+ }
11
13
 
12
- matchers.each do |type, matcher|
13
- STDOUT.sync = true
14
- Dir.chdir("./test/#{type}") do
15
- print "Testing #{type}#{' ' * (22 - type.size )}"
16
- fork {
17
- ENV['BUNDLE_GEMFILE'] = File.expand_path("./Gemfile")
18
- out = `bundle && bundle exec rake 2>&1`
19
- if matcher.all?{|m|out[m]}
20
- exit
21
- else
22
- puts out
23
- exit 1
24
- end
25
- }
26
- _, status = Process.wait2
27
- puts status.success? ? "PASSED" : "FAILED"
14
+ matchers.each do |type, matcher|
15
+ STDOUT.sync = true
16
+ Dir.chdir("./test/#{type}") do
17
+ print "Testing #{type}#{' ' * (22 - type.size )}"
18
+ fork {
19
+ ENV['BUNDLE_GEMFILE'] = File.expand_path("./Gemfile")
20
+ out = `bundle && bundle exec rake 2>&1`
21
+ if matcher.all?{|m|out[m]}
22
+ exit
23
+ else
24
+ puts out
25
+ exit 1
26
+ end
27
+ }
28
+ _, status = Process.wait2
29
+ puts status.success? ? "PASSED" : "FAILED"
30
+ end
28
31
  end
29
32
  end
30
33
 
31
- # test README.md
32
- require 'minitest/autorun'
33
- require 'eventmachine'
34
- $LOAD_PATH << 'lib'
35
- require 'em-ventually'
36
- class ReadmeTest < MiniTest::Unit::TestCase
37
- include EM::Ventually
38
-
34
+ task :readme do
35
+ # test README.md
36
+ puts "Testing README.md"
37
+ STDOUT.sync = true
39
38
  readme = File.read('./README.md')
40
- readme.scan(/~~~~~ \{ruby\}\n(.*?)~~~~~/m).each do |block|
41
- class_eval(block.join)
39
+ passes = readme.scan(/~~~~~ \{ruby\}\n(.*?)~~~~~/m).map do |block|
40
+ fork {
41
+ require 'minitest/autorun'
42
+ require 'eventmachine'
43
+ $LOAD_PATH << 'lib'
44
+ STDOUT.reopen('/dev/null')
45
+ require 'em-ventually'
46
+ code = block.join
47
+ cls = Class.new(MiniTest::Unit::TestCase)
48
+ cls.class_eval "include EM::Ventually" unless code[/# Without em-ventually/]
49
+ cls.class_eval(code)
50
+ cls
51
+ }
52
+ _, status = Process.wait2
53
+ print status.success? ? '.' : 'F'
54
+ status.success? ? :pass : :fail
42
55
  end
56
+ puts
57
+ pass_count = passes.inject(0){|m, s| m += (s == :pass ? 1 : 0)}
58
+ raise "README tests failed" unless pass_count == passes.size
43
59
  end
44
- end
45
-
60
+ end
data/lib/em-ventually.rb CHANGED
@@ -43,6 +43,10 @@ module EventMachine
43
43
  end
44
44
  alias_method :ly, :eventually
45
45
 
46
+ def manually_stop_em!
47
+ @_manually_stop_em = true
48
+ end
49
+
46
50
  def parallel(&blk)
47
51
  _pool.in_parallel do
48
52
  instance_eval(&blk)
@@ -10,7 +10,9 @@ module EventMachine
10
10
  begin
11
11
  result = yield
12
12
  ensure
13
- EM.stop if (!instance_variable_defined?(:@_pool) || @_pool.nil? || @_pool.empty?) && EM.reactor_running?
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
14
16
  end
15
17
  end
16
18
  end
@@ -1,5 +1,5 @@
1
1
  module EventMachine
2
2
  module Ventually
3
- VERSION = "0.1.1"
3
+ VERSION = "0.1.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-ventually
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Josh Hull
@@ -15,13 +15,12 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-08 00:00:00 -07:00
18
+ date: 2011-08-17 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: eventmachine
23
22
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
25
  requirements:
27
26
  - - ">="
@@ -30,12 +29,12 @@ dependencies:
30
29
  segments:
31
30
  - 0
32
31
  version: "0"
32
+ requirement: *id001
33
+ name: eventmachine
33
34
  type: :runtime
34
- version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
- name: callsite
37
36
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
37
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
38
  none: false
40
39
  requirements:
41
40
  - - ~>
@@ -46,12 +45,12 @@ dependencies:
46
45
  - 0
47
46
  - 5
48
47
  version: 0.0.5
48
+ requirement: *id002
49
+ name: callsite
49
50
  type: :runtime
50
- version_requirements: *id002
51
51
  - !ruby/object:Gem::Dependency
52
- name: code_stats
53
52
  prerelease: false
54
- requirement: &id003 !ruby/object:Gem::Requirement
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
55
54
  none: false
56
55
  requirements:
57
56
  - - ">="
@@ -60,12 +59,12 @@ dependencies:
60
59
  segments:
61
60
  - 0
62
61
  version: "0"
62
+ requirement: *id003
63
+ name: code_stats
63
64
  type: :development
64
- version_requirements: *id003
65
65
  - !ruby/object:Gem::Dependency
66
- name: rake
67
66
  prerelease: false
68
- requirement: &id004 !ruby/object:Gem::Requirement
67
+ version_requirements: &id004 !ruby/object:Gem::Requirement
69
68
  none: false
70
69
  requirements:
71
70
  - - ~>
@@ -76,12 +75,12 @@ dependencies:
76
75
  - 8
77
76
  - 7
78
77
  version: 0.8.7
78
+ requirement: *id004
79
+ name: rake
79
80
  type: :development
80
- version_requirements: *id004
81
81
  - !ruby/object:Gem::Dependency
82
- name: phocus
83
82
  prerelease: false
84
- requirement: &id005 !ruby/object:Gem::Requirement
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
85
84
  none: false
86
85
  requirements:
87
86
  - - ">="
@@ -90,12 +89,12 @@ dependencies:
90
89
  segments:
91
90
  - 0
92
91
  version: "0"
92
+ requirement: *id005
93
+ name: phocus
93
94
  type: :development
94
- version_requirements: *id005
95
95
  - !ruby/object:Gem::Dependency
96
- name: bundler
97
96
  prerelease: false
98
- requirement: &id006 !ruby/object:Gem::Requirement
97
+ version_requirements: &id006 !ruby/object:Gem::Requirement
99
98
  none: false
100
99
  requirements:
101
100
  - - ~>
@@ -106,12 +105,12 @@ dependencies:
106
105
  - 0
107
106
  - 0
108
107
  version: 1.0.0
108
+ requirement: *id006
109
+ name: bundler
109
110
  type: :development
110
- version_requirements: *id006
111
111
  - !ruby/object:Gem::Dependency
112
- name: minitest
113
112
  prerelease: false
114
- requirement: &id007 !ruby/object:Gem::Requirement
113
+ version_requirements: &id007 !ruby/object:Gem::Requirement
115
114
  none: false
116
115
  requirements:
117
116
  - - ~>
@@ -122,8 +121,9 @@ dependencies:
122
121
  - 0
123
122
  - 0
124
123
  version: 2.0.0
124
+ requirement: *id007
125
+ name: minitest
125
126
  type: :development
126
- version_requirements: *id007
127
127
  description: Eventually, your tests should pass in EventMachine.
128
128
  email:
129
129
  - joshbuddy@gmail.com