fire_poll 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ doc
5
+ .yardoc
@@ -0,0 +1 @@
1
+ --markup markdown --readme README.md
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fire_poll.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ (the MIT license)
2
+ Copyright 2011 by Atomic Object
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
@@ -0,0 +1,77 @@
1
+ Description
2
+ ===========
3
+ `FirePoll.poll` is a method for knowing when something is ready. When your block yields true, execution continues. When your block yields false, poll keeps trying until it gives up and raises an error.
4
+
5
+ Examples
6
+ --------
7
+ I'm writing a system test for a web application. My test simulates uploading a large file, which isn't instantaneous. I need to know when the file has finished uploading so I can start making assertions.
8
+ def wait_for_file(filename)
9
+ FirePoll.poll do
10
+ FileStore.file_ready?(filename)
11
+ end
12
+ end
13
+
14
+ def test_files_are_saved
15
+ upload_file "blue.txt"
16
+ assert_nothing_raised { wait_for_file "blue.txt" }
17
+ assert_equal "blue is the best color", read_saved_file("blue.txt")
18
+ end
19
+
20
+ I just fired up a fake web service to respond to my client application. I want to know when the service is online before I start the client tests. I'm willing to wait 10 seconds before giving up.
21
+ class TestHelper
22
+ include FirePoll
23
+
24
+ def wait_for_server
25
+ poll("server didn't come online quick enough", 10) do
26
+ begin
27
+ TCPSocket.new(SERVER_IP, SERVER_PORT)
28
+ true
29
+ rescue Exception
30
+ false
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ Usage
37
+ -----
38
+ Pass a block to `FirePoll.poll`. Return `true` when your need is met. Return `false` when it isn't. `poll` will raise an exception after too many failed attempts.
39
+
40
+ The `poll` method takes two optional parameters: a specific message to raise on failure and the number of seconds to wait. By default, `poll` will try for two seconds. `poll` runs every tenth of a second.
41
+ FirePoll.poll { ... } # raises an error after two seconds
42
+ FirePoll.poll("new data hasn't arrived from the device") { ... } # raises a friendlier error message
43
+ FirePoll.poll("waited for too long!", 7) { ... } # raises an error after seven seconds with a specific error message
44
+ FirePoll.poll(nil, 88) { ... } # raises an error after eighty-eight seconds with the generic error message
45
+
46
+ The `FirePoll` module may be mixed into your class; this makes it a little faster to type the method name.
47
+ class TestHelper
48
+ include FirePoll
49
+ def helper_method
50
+ poll do
51
+ ...
52
+ end
53
+ end
54
+ end
55
+
56
+ Implementation
57
+ --------------
58
+ `FirePoll.poll`'s implementation isn't partcilarly accurate with respect to time. The method will run your block (number of seconds * 10) times. It sleeps for a tenth of a second between attempts. Since it doesn't keep track of time, if your timing needs require accuracy, you'll need to look elsewhere.
59
+
60
+ Motivation
61
+ ----------
62
+ We frequently need to wait for something to happen - usually in tests. And we usually don't have any strict time requirements - as long as something happens in _about_ [x] seconds, we're happy. `FirePoll.poll` meets our need nicely.
63
+
64
+ On a related note, `Timer::Timeout` is known to be [busted](http://ph7spot.com/musings/system-timer) and [unreliable](http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html). `FirePoll.poll` doesn't employ any threads or timers, so we don't worry about whether it will work or not.
65
+
66
+ TODO
67
+ ----
68
+ * Nice to have: hook into Test::Unit and RSpec instead of raising a Ruby exception
69
+ * Nice to have: pass options as a hash instead of two parameters. This will look nice with Ruby 1.9's hash syntax.
70
+
71
+ Authors
72
+ =======
73
+ * Matt Fletcher (fletcher@atomicobject.com)
74
+ * David Crosby (crosby@atomicobject.com)
75
+ * Micah Alles (alles@atomicobject.com)
76
+ * © 2011 [Atomic Object](http://www.atomicobject.com/)
77
+ * More Atomic Object [open source](http://www.atomicobject.com/pages/Software+Commons) projects
@@ -0,0 +1,19 @@
1
+ require "bundler"
2
+ require "rake/testtask"
3
+ require "rake/clean"
4
+ require "yard"
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.test_files = FileList["test/test*.rb"]
9
+ end
10
+
11
+ YARD::Rake::YardocTask.new do |t|
12
+ t.files = %w[ lib/fire_poll.rb ]
13
+ end
14
+
15
+ CLEAN.include "pkg"
16
+ CLEAN.include "doc"
17
+ CLEAN.include ".yardoc"
18
+
19
+ task :default => :test
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "fire_poll/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "fire_poll"
7
+ s.version = FirePoll::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Matt Fletcher", "David Crosby", "Micah Alles"]
10
+ s.email = ["fletcher@atomicobject.com", "crosby@atomicobject.com", "alles@atomicobject.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Simple, brute-force method for knowing when something is ready}
13
+ s.description = %q{Simple, brute-force method for knowing when something is ready}
14
+
15
+ s.rubyforge_project = "fire_poll"
16
+
17
+ s.add_development_dependency("bundler", ">= 1.0.0")
18
+ s.add_development_dependency("rake", ">= 0.8.0")
19
+ s.add_development_dependency("yard", "~> 0.6.4")
20
+ s.add_development_dependency("bluecloth", "~> 2.0.11")
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
@@ -0,0 +1,22 @@
1
+ # see the {file:README.md README file} for instruction on how to use this library
2
+ module FirePoll
3
+ # @param [String] msg a custom message raised when polling fails
4
+ # @param [Numeric] seconds number of seconds to poll
5
+ # @yield a block that determines whether polling should continue
6
+ # @yieldreturn false if polling should continue
7
+ # @yieldreturn true if polling is complete
8
+ # @raise [RuntimeError] when polling fails
9
+ # @return [NilClass]
10
+ # @since 1.0.0
11
+ def poll(msg=nil, seconds=2.0)
12
+ (seconds * 10).to_i.times do
13
+ return if yield
14
+ sleep 0.1
15
+ end
16
+ msg ||= "polling failed after #{seconds} seconds"
17
+ raise msg
18
+ nil
19
+ end
20
+
21
+ module_function :poll
22
+ end
@@ -0,0 +1,3 @@
1
+ module FirePoll
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,67 @@
1
+ require "test/unit"
2
+ require "fire_poll"
3
+
4
+ class FirePollTest < Test::Unit::TestCase
5
+ def test_raises_when_block_does_not_yield_true
6
+ assert_raise RuntimeError do
7
+ FirePoll.poll { false }
8
+ end
9
+ end
10
+
11
+ def test_does_not_raise_when_block_yields_true
12
+ assert_nothing_raised do
13
+ FirePoll.poll { true }
14
+ end
15
+ end
16
+
17
+ def test_does_not_raise_when_block_eventually_yields_true
18
+ assert_nothing_raised do
19
+ count = 0
20
+ FirePoll.poll do
21
+ count += 1
22
+ count > 5 ? true : false
23
+ end
24
+ end
25
+ end
26
+
27
+ def test_can_take_an_optional_number_of_seconds_to_poll
28
+ # default 2 seconds = 20 calls to the block
29
+ assert_nothing_raised do
30
+ count1 = 0
31
+ FirePoll.poll do
32
+ count1 += 1
33
+ count1 > 11 ? true : false
34
+ end
35
+ end
36
+
37
+ # 1 second = 10 calls to the block
38
+ assert_raise RuntimeError do
39
+ count = 0
40
+ FirePoll.poll(nil, 1) do
41
+ count += 1
42
+ count > 11 ? true : false
43
+ end
44
+ end
45
+ end
46
+
47
+ def test_can_take_an_optional_message
48
+ # anyone know a better way to do this with straight-up Test::Unit?
49
+ begin
50
+ FirePoll.poll("custom message") { false }
51
+ rescue RuntimeError => ex
52
+ assert_equal "custom message", ex.message
53
+ return
54
+ end
55
+ flunk "should have raised"
56
+ end
57
+ end
58
+
59
+ class TestFirePollMixin < Test::Unit::TestCase
60
+ include FirePoll
61
+
62
+ def test_can_be_mixed_in
63
+ assert_nothing_raised do
64
+ poll { true }
65
+ end
66
+ end
67
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fire_poll
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Matt Fletcher
13
+ - David Crosby
14
+ - Micah Alles
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-02-23 00:00:00 -05:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: bundler
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ segments:
46
+ - 0
47
+ - 8
48
+ - 0
49
+ version: 0.8.0
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: yard
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ - 6
63
+ - 4
64
+ version: 0.6.4
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: bluecloth
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 2
77
+ - 0
78
+ - 11
79
+ version: 2.0.11
80
+ type: :development
81
+ version_requirements: *id004
82
+ description: Simple, brute-force method for knowing when something is ready
83
+ email:
84
+ - fletcher@atomicobject.com
85
+ - crosby@atomicobject.com
86
+ - alles@atomicobject.com
87
+ executables: []
88
+
89
+ extensions: []
90
+
91
+ extra_rdoc_files: []
92
+
93
+ files:
94
+ - .gitignore
95
+ - .yardopts
96
+ - Gemfile
97
+ - LICENSE
98
+ - README.md
99
+ - Rakefile
100
+ - fire_poll.gemspec
101
+ - lib/fire_poll.rb
102
+ - lib/fire_poll/version.rb
103
+ - test/test_fire_poll.rb
104
+ has_rdoc: true
105
+ homepage: ""
106
+ licenses: []
107
+
108
+ post_install_message:
109
+ rdoc_options: []
110
+
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ requirements: []
130
+
131
+ rubyforge_project: fire_poll
132
+ rubygems_version: 1.3.7
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: Simple, brute-force method for knowing when something is ready
136
+ test_files:
137
+ - test/test_fire_poll.rb