govdelivery-proctor 1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +34 -0
- data/README.md +93 -0
- data/Rakefile +8 -0
- data/lib/govdelivery-proctor.rb +6 -0
- data/lib/govdelivery/proctor/base.rb +109 -0
- data/lib/govdelivery/proctor/version.rb +5 -0
- data/proctor.gemspec +24 -0
- data/test/test_helper.rb +8 -0
- data/test/test_proctor.rb +101 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bce8d79f6531e5607f2cc402de70da89aa6c961a
|
4
|
+
data.tar.gz: cc01c5f9d058db7f0aacff5ecffa1141417dac37
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1047b2266805be8100f8d365a36952e4a91afb18dac09a15a84c9563094971fbf3ace15ff6b5a0823aa0340c62eaf72a0f98f180e2c91392f016d3258e40cdd6
|
7
|
+
data.tar.gz: 75b16d48140304a9cab0cf1343b2f153cda23bd7ca0ee77a02ecd5d901fade3c8b3ba8be2269aae0ca67aba32400bf5247f255c70d8b1ae2ef8c267946f1391f
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
|
+
|
5
|
+
[How to use a CHANGELOG](http://keepachangelog.com/)
|
6
|
+
## [1.3.0]
|
7
|
+
### Added
|
8
|
+
- Say hello to steady_check which sleeps for the increment passed to it
|
9
|
+
### Fixed
|
10
|
+
- accelerating_check algorithm was messed up, so now using `log` to better approximate reverse of backoff_check
|
11
|
+
## [1.2.1]
|
12
|
+
### Fixed
|
13
|
+
- backoff_check and accelerating_check now reset the logger when finished.
|
14
|
+
- Corrected README documentation about accelerating_check
|
15
|
+
## [1.2.0]
|
16
|
+
### Added
|
17
|
+
- reverse backoff added for situations when the likelihood of the condition being true increases over time
|
18
|
+
## [1.1.1]
|
19
|
+
### Fixed
|
20
|
+
- Removed references to the `colored` gem, which was never required, or that useful
|
21
|
+
## [1.1.0]
|
22
|
+
### Updated
|
23
|
+
- backoff_check to only log out on failure.
|
24
|
+
## [1.0.0] - 2016-03-21
|
25
|
+
### Added
|
26
|
+
- backoff_check, log, and suppress class methods on GovDelivery::Proctor
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
govdelivery-proctor (1.2.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
byebug (9.0.5)
|
10
|
+
coderay (1.1.1)
|
11
|
+
method_source (0.8.2)
|
12
|
+
power_assert (0.3.0)
|
13
|
+
pry (0.10.4)
|
14
|
+
coderay (~> 1.1.0)
|
15
|
+
method_source (~> 0.8.1)
|
16
|
+
slop (~> 3.4)
|
17
|
+
pry-byebug (3.4.0)
|
18
|
+
byebug (~> 9.0)
|
19
|
+
pry (~> 0.10)
|
20
|
+
slop (3.6.0)
|
21
|
+
test-unit (3.2.1)
|
22
|
+
power_assert
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
bundler (~> 1.7)
|
29
|
+
govdelivery-proctor!
|
30
|
+
pry-byebug (~> 3.4)
|
31
|
+
test-unit
|
32
|
+
|
33
|
+
BUNDLED WITH
|
34
|
+
1.13.6
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
Proctor
|
2
|
+
===========
|
3
|
+
|
4
|
+
Classes and functions to support feature testing.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'govdelivery-proctor'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install govdelivery-proctor
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Include it: `require 'govdelivery-proctor'`
|
25
|
+
|
26
|
+
### backoff_check
|
27
|
+
|
28
|
+
`GovDelivery::Proctor.backoff_check` will run a provided block, over and over
|
29
|
+
with longer and longer waits between runs, until the provided block either
|
30
|
+
returns a truthy value or exceeds a provided max time to wait. At the end
|
31
|
+
of each unsuccessful run - a run that does not return a truthy value - a
|
32
|
+
message will be written to the log based on the provided message string.
|
33
|
+
|
34
|
+
```
|
35
|
+
tomorrow = Time.new.day + 1.day
|
36
|
+
GovDelivery::Proctor.backoff_check(24.hours, "Waiting for tomorrow") do
|
37
|
+
Time.new.day == tomorrow
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
### accelerating_check
|
42
|
+
|
43
|
+
`GovDelivery::Proctor.accelerating_check` will run a provided block, over and over
|
44
|
+
with shorter and shorter waits between runs, until the provided block either
|
45
|
+
returns a truthy value or exceeds a provided max time to wait. At the end
|
46
|
+
of each unsuccessful run - a run that does not return a truthy value - a
|
47
|
+
message will be written to the log based on the provided message string.
|
48
|
+
|
49
|
+
### steady_check
|
50
|
+
|
51
|
+
`GovDelivery::Proctor.steady_check` will run a provided block, over and over
|
52
|
+
with the specified wait between every run, until the provided block either
|
53
|
+
returns a truthy value or exceeds a provided max time to wait. At the end
|
54
|
+
of each unsuccessful run - a run that does not return a truthy value - a
|
55
|
+
message will be written to the log based on the provided message string.
|
56
|
+
|
57
|
+
### log
|
58
|
+
|
59
|
+
Returns a logger object for logging/outputing. By default, this logger object
|
60
|
+
will print to `STDOUT` and have a level of `INFO`. These can be set via the
|
61
|
+
environment variables `TEST_LOG_FILE` and `TEST_LOG_LEVEL` respectively.
|
62
|
+
|
63
|
+
```
|
64
|
+
GovDelivery::Proctor.log.info('Nothing is real') unless 1 == 1
|
65
|
+
```
|
66
|
+
|
67
|
+
### suppress
|
68
|
+
|
69
|
+
Runs a provided block and ignores if a specified exception is thrown.
|
70
|
+
|
71
|
+
```
|
72
|
+
GovDelivery::Proctor.suppress(ZeroDivisionError) do
|
73
|
+
1/0
|
74
|
+
puts 'Nothing wrong here'
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
## Development
|
79
|
+
### Get Dev Dependencies
|
80
|
+
|
81
|
+
$ bundle install
|
82
|
+
|
83
|
+
### Build
|
84
|
+
|
85
|
+
$ gem build proctor.gemspec
|
86
|
+
|
87
|
+
### Install locally
|
88
|
+
|
89
|
+
$ gem install govdelivery-proctor-1.2.0.gem
|
90
|
+
|
91
|
+
### Test
|
92
|
+
|
93
|
+
$ rake test
|
data/Rakefile
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module GovDelivery::Proctor
|
2
|
+
class CheckTimeExceeded < StandardError; end
|
3
|
+
|
4
|
+
def self.backoff_check(limit, desc = 'Backoff check', inc = 1)
|
5
|
+
raise 'Check requires a block' unless block_given?
|
6
|
+
check(limit, 'backoff', desc, inc) do
|
7
|
+
yield
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Sometimes you want to reverse backoff because as time
|
12
|
+
# passes it is more likely your condition is true
|
13
|
+
def self.accelerating_check(limit, desc = 'Backon check', inc = 1)
|
14
|
+
raise 'Check requires a block' unless block_given?
|
15
|
+
check(limit, 'accelerate', desc, inc) do
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.steady_check(limit, desc = 'Steady check', inc = 1)
|
21
|
+
raise 'Check requires a block' unless block_given?
|
22
|
+
check(limit, 'steady', desc, inc) do
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# if backoff, double the wait time each time
|
28
|
+
# if accelerating, ramp up after long pause
|
29
|
+
# if steady, just keep it steady
|
30
|
+
def self.sleep_time(check_type, limit, increment, iteration)
|
31
|
+
case check_type
|
32
|
+
when 'steady'
|
33
|
+
increment
|
34
|
+
when 'backoff'
|
35
|
+
(2**iteration) * increment
|
36
|
+
when 'accelerate'
|
37
|
+
val = Math.log(limit, iteration + 1)
|
38
|
+
val = val.to_f.infinite? ? limit / increment : val
|
39
|
+
val = val.to_f.nan? ? 1 : val.round
|
40
|
+
[increment, val * increment].max
|
41
|
+
else
|
42
|
+
raise "Check type #{check_type} invalid: choose backon, accelerate or steady."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.check(limit, check_type, desc, inc)
|
47
|
+
setup
|
48
|
+
|
49
|
+
slept_time = 0
|
50
|
+
x = 0
|
51
|
+
response = nil
|
52
|
+
Kernel.loop do
|
53
|
+
sleep_time = sleep_time(check_type, limit, inc, ++x)
|
54
|
+
sleep(sleep_time)
|
55
|
+
slept_time += sleep_time
|
56
|
+
response = yield
|
57
|
+
break if response
|
58
|
+
if slept_time >= limit
|
59
|
+
fail_message = "#{desc} has taken too long. Have waited #{slept_time} seconds\nlog: #{@backBuffer.string}"
|
60
|
+
raise CheckTimeExceeded, fail_message
|
61
|
+
end
|
62
|
+
# We're doing this twice, once for standard out so you can see it's still
|
63
|
+
# working, and then again inside the logged output if it fails.
|
64
|
+
|
65
|
+
getStandardLogger.info("Still waiting while #{desc}, current time=#{slept_time}")
|
66
|
+
log.info("Still waiting while #{desc}, current time=#{slept_time}")
|
67
|
+
end
|
68
|
+
teardown
|
69
|
+
response
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.log
|
73
|
+
getStandardLogger
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.suppress(*exception_classes)
|
77
|
+
yield
|
78
|
+
rescue *exception_classes
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.getStandardLogger
|
82
|
+
@log ||= begin
|
83
|
+
logger = Logger.new(ENV['TEST_LOG_FILE'] || STDOUT)
|
84
|
+
logger.level = Logger.const_get(ENV['TEST_LOG_LEVEL'] || 'INFO')
|
85
|
+
logger
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.setup
|
90
|
+
@backBuffer = StringIO.new
|
91
|
+
@backLog = Logger.new @backBuffer
|
92
|
+
|
93
|
+
# We're re-defining log in here so that we can log meaningful information
|
94
|
+
# out during the backoff check, but only for failed runs.
|
95
|
+
def self.log
|
96
|
+
@backLog
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.teardown
|
101
|
+
# We have to re-define log back to it's original implementation
|
102
|
+
# so that we get normal logging after we're out of the backoff check.
|
103
|
+
def self.log
|
104
|
+
getStandardLogger
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
private_class_method :getStandardLogger, :setup, :teardown
|
109
|
+
end
|
data/proctor.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'govdelivery/proctor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'govdelivery-proctor'
|
8
|
+
spec.version = GovDelivery::Proctor::VERSION
|
9
|
+
spec.authors = ['Bill Bushey']
|
10
|
+
spec.email = ['bill.bushey@govdelivery.com']
|
11
|
+
spec.summary = 'Classes and functions to support feature testing.'
|
12
|
+
spec.description = 'Classes and functions to support feature testing.'
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'test-unit'
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
23
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.4'
|
24
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module GovDelivery::Proctor
|
4
|
+
require 'logger'
|
5
|
+
end
|
6
|
+
|
7
|
+
class TestProctor < Test::Unit::TestCase
|
8
|
+
def test_sleep_time_steady
|
9
|
+
assert_equal 30, GovDelivery::Proctor.sleep_time('steady', 600, 30, 5)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_sleep_time_backoff_iteration_one
|
13
|
+
assert_equal 60, GovDelivery::Proctor.sleep_time('backoff', 600, 30, 1)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_sleep_time_backoff_iteration_four
|
17
|
+
assert_equal 480, GovDelivery::Proctor.sleep_time('backoff', 600, 30, 4)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_sleep_time_accelerate_iteration_default_to_minimum
|
21
|
+
assert_equal 10, GovDelivery::Proctor.sleep_time('accelerate', 1, 10, 2)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_sleep_time_accelerate_iteration_one
|
25
|
+
assert_equal 90, GovDelivery::Proctor.sleep_time('accelerate', 600, 10, 1)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_sleep_time_accelerate_iteration_four
|
29
|
+
assert_equal 40, GovDelivery::Proctor.sleep_time('accelerate', 600, 10, 4)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_sleep_time_accelerate_iteration_four_lower_sleep
|
33
|
+
assert_equal 4, GovDelivery::Proctor.sleep_time('accelerate', 600, 1, 4)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_backoff_check_condition_true
|
37
|
+
GovDelivery::Proctor.backoff_check 2 do
|
38
|
+
true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_accelerating_check_condition_true
|
43
|
+
GovDelivery::Proctor.accelerating_check 2 do
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_steady_check_condition_true
|
49
|
+
GovDelivery::Proctor.steady_check 2 do
|
50
|
+
true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_backoff_check_condition_false
|
55
|
+
ex = assert_raises GovDelivery::Proctor::CheckTimeExceeded do
|
56
|
+
GovDelivery::Proctor.backoff_check 1 do
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
assert_equal "Backoff check has taken too long. Have waited 1 seconds\nlog: ", ex.message
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_accelerating_check_condition_false
|
64
|
+
ex = assert_raises GovDelivery::Proctor::CheckTimeExceeded do
|
65
|
+
GovDelivery::Proctor.accelerating_check 1 do
|
66
|
+
false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
assert_equal "Backon check has taken too long. Have waited 1 seconds\nlog: ", ex.message
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_steady_check_condition_false
|
73
|
+
ex = assert_raises GovDelivery::Proctor::CheckTimeExceeded do
|
74
|
+
GovDelivery::Proctor.steady_check 1 do
|
75
|
+
false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
assert_equal "Steady check has taken too long. Have waited 1 seconds\nlog: ", ex.message
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_backoff_check_requires_block
|
82
|
+
ex = assert_raises RuntimeError do
|
83
|
+
GovDelivery::Proctor.backoff_check 1
|
84
|
+
end
|
85
|
+
assert_equal 'Check requires a block', ex.message
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_accelerating_check_requires_block
|
89
|
+
ex = assert_raises RuntimeError do
|
90
|
+
GovDelivery::Proctor.accelerating_check 1
|
91
|
+
end
|
92
|
+
assert_equal 'Check requires a block', ex.message
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_steady_check_requires_block
|
96
|
+
ex = assert_raises RuntimeError do
|
97
|
+
GovDelivery::Proctor.steady_check 1
|
98
|
+
end
|
99
|
+
assert_equal 'Check requires a block', ex.message
|
100
|
+
end
|
101
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: govdelivery-proctor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.3'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bill Bushey
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: test-unit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.4'
|
55
|
+
description: Classes and functions to support feature testing.
|
56
|
+
email:
|
57
|
+
- bill.bushey@govdelivery.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- CHANGELOG.md
|
64
|
+
- Gemfile
|
65
|
+
- Gemfile.lock
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- lib/govdelivery-proctor.rb
|
69
|
+
- lib/govdelivery/proctor/base.rb
|
70
|
+
- lib/govdelivery/proctor/version.rb
|
71
|
+
- proctor.gemspec
|
72
|
+
- test/test_helper.rb
|
73
|
+
- test/test_proctor.rb
|
74
|
+
homepage: ''
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.5.1
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: Classes and functions to support feature testing.
|
98
|
+
test_files:
|
99
|
+
- test/test_helper.rb
|
100
|
+
- test/test_proctor.rb
|