adrian 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/adrian/directory_queue.rb +5 -6
- data/lib/adrian/file_item.rb +9 -8
- data/lib/adrian/version.rb +1 -1
- metadata +15 -51
- data/CONTRIBUTING.md +0 -7
- data/README.md +0 -34
- data/test/array_queue_test.rb +0 -33
- data/test/composite_queue_test.rb +0 -44
- data/test/directory_queue_test.rb +0 -153
- data/test/dispatcher_lifecycle_test.rb +0 -82
- data/test/dispatcher_test.rb +0 -99
- data/test/failure_handler_test.rb +0 -44
- data/test/file_item_test.rb +0 -152
- data/test/filters_test.rb +0 -105
- data/test/girl_friday_dispatcher_test.rb +0 -28
- data/test/queue_test.rb +0 -48
- data/test/rotating_directory_queue_test.rb +0 -55
- data/test/test_helper.rb +0 -13
- data/test/worker_test.rb +0 -38
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8f73a613da14daf5853a7cf3293d631206cccb95
|
4
|
+
data.tar.gz: a334dbf9245a776ab4c8183ce2bd85ccb63b432c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 63b1f95bf533968cc32cb7f483af6747199c4d8b0623a55ffbbc5165b493166196a1571a3a651347ae9e1c3a291e1b6a5b40d8d54b84e28d8eaeba0e3e1badcf
|
7
|
+
data.tar.gz: 1f874b8b498ac09771a4a11c2dad9cb3bbcfc890ca9d40d862d564b160a56ba03e1202460c8b21a96a15faa4c3869716291ab02b55fbcec5bd7aa5093af4eae0
|
@@ -29,11 +29,9 @@ module Adrian
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def pop_item
|
32
|
-
items.
|
32
|
+
while item = items.shift
|
33
33
|
return item if reserve(item)
|
34
34
|
end
|
35
|
-
|
36
|
-
nil
|
37
35
|
end
|
38
36
|
|
39
37
|
def push_item(value)
|
@@ -69,9 +67,10 @@ module Adrian
|
|
69
67
|
end
|
70
68
|
|
71
69
|
def items
|
72
|
-
items
|
73
|
-
items.
|
74
|
-
items.
|
70
|
+
return @items if @items && @items.length > 0
|
71
|
+
@items = files.map! { |file| wrap_item(file) }
|
72
|
+
@items.reject! { |item| !item.exist? || filter?(item) }
|
73
|
+
@items.sort_by!(&:updated_at)
|
75
74
|
end
|
76
75
|
|
77
76
|
def files
|
data/lib/adrian/file_item.rb
CHANGED
@@ -3,9 +3,8 @@ module Adrian
|
|
3
3
|
attr_accessor :logger
|
4
4
|
|
5
5
|
def initialize(value)
|
6
|
-
@value
|
7
|
-
|
8
|
-
updated_at
|
6
|
+
@value = value
|
7
|
+
stat
|
9
8
|
end
|
10
9
|
|
11
10
|
def path
|
@@ -28,16 +27,18 @@ module Adrian
|
|
28
27
|
@value = destination_path
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
32
|
-
File.
|
30
|
+
def stat
|
31
|
+
@stat ||= File.stat(path)
|
33
32
|
rescue Errno::ENOENT
|
34
33
|
nil
|
35
34
|
end
|
36
35
|
|
36
|
+
def atime
|
37
|
+
stat ? stat.atime.utc : nil
|
38
|
+
end
|
39
|
+
|
37
40
|
def mtime
|
38
|
-
|
39
|
-
rescue Errno::ENOENT
|
40
|
-
nil
|
41
|
+
stat ? stat.mtime.utc : nil
|
41
42
|
end
|
42
43
|
|
43
44
|
def updated_at
|
data/lib/adrian/version.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adrian
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Mick Staugaard
|
@@ -10,54 +9,48 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2015-05-22 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rake
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '0'
|
23
21
|
type: :development
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - '>='
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '0'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: minitest
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - '>='
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: '0'
|
39
35
|
type: :development
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '>='
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: '0'
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: girl_friday
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - '>='
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '0'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - '>='
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '0'
|
63
56
|
description: A work dispatcher and some queue implementations
|
@@ -66,6 +59,7 @@ executables: []
|
|
66
59
|
extensions: []
|
67
60
|
extra_rdoc_files: []
|
68
61
|
files:
|
62
|
+
- lib/adrian.rb
|
69
63
|
- lib/adrian/array_queue.rb
|
70
64
|
- lib/adrian/composite_queue.rb
|
71
65
|
- lib/adrian/directory_queue.rb
|
@@ -79,58 +73,28 @@ files:
|
|
79
73
|
- lib/adrian/rotating_directory_queue.rb
|
80
74
|
- lib/adrian/version.rb
|
81
75
|
- lib/adrian/worker.rb
|
82
|
-
- lib/adrian.rb
|
83
|
-
- test/array_queue_test.rb
|
84
|
-
- test/composite_queue_test.rb
|
85
|
-
- test/directory_queue_test.rb
|
86
|
-
- test/dispatcher_lifecycle_test.rb
|
87
|
-
- test/dispatcher_test.rb
|
88
|
-
- test/failure_handler_test.rb
|
89
|
-
- test/file_item_test.rb
|
90
|
-
- test/filters_test.rb
|
91
|
-
- test/girl_friday_dispatcher_test.rb
|
92
|
-
- test/queue_test.rb
|
93
|
-
- test/rotating_directory_queue_test.rb
|
94
|
-
- test/test_helper.rb
|
95
|
-
- test/worker_test.rb
|
96
|
-
- README.md
|
97
|
-
- CONTRIBUTING.md
|
98
76
|
homepage: https://github.com/zendesk/adrian
|
99
77
|
licenses:
|
100
78
|
- Apache License Version 2.0
|
79
|
+
metadata: {}
|
101
80
|
post_install_message:
|
102
81
|
rdoc_options: []
|
103
82
|
require_paths:
|
104
83
|
- lib
|
105
84
|
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
85
|
requirements:
|
108
|
-
- -
|
86
|
+
- - '>='
|
109
87
|
- !ruby/object:Gem::Version
|
110
88
|
version: '0'
|
111
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
-
none: false
|
113
90
|
requirements:
|
114
|
-
- -
|
91
|
+
- - '>='
|
115
92
|
- !ruby/object:Gem::Version
|
116
93
|
version: '0'
|
117
94
|
requirements: []
|
118
95
|
rubyforge_project:
|
119
|
-
rubygems_version:
|
96
|
+
rubygems_version: 2.0.14
|
120
97
|
signing_key:
|
121
|
-
specification_version:
|
98
|
+
specification_version: 4
|
122
99
|
summary: Adrian does not do any real work, but is really good at delegating it
|
123
|
-
test_files:
|
124
|
-
- test/array_queue_test.rb
|
125
|
-
- test/composite_queue_test.rb
|
126
|
-
- test/directory_queue_test.rb
|
127
|
-
- test/dispatcher_lifecycle_test.rb
|
128
|
-
- test/dispatcher_test.rb
|
129
|
-
- test/failure_handler_test.rb
|
130
|
-
- test/file_item_test.rb
|
131
|
-
- test/filters_test.rb
|
132
|
-
- test/girl_friday_dispatcher_test.rb
|
133
|
-
- test/queue_test.rb
|
134
|
-
- test/rotating_directory_queue_test.rb
|
135
|
-
- test/test_helper.rb
|
136
|
-
- test/worker_test.rb
|
100
|
+
test_files: []
|
data/CONTRIBUTING.md
DELETED
data/README.md
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# Adrian
|
2
|
-
|
3
|
-
Adrian is a work dispatcher and some queue implementations.
|
4
|
-
Adrian does not do any real work, but is really good at delegating it.
|
5
|
-
Adrian **does not care how** real work get's done, but **makes damn sure that it does get done**.
|
6
|
-
|
7
|
-
## Installation
|
8
|
-
|
9
|
-
Add this line to your application's Gemfile:
|
10
|
-
|
11
|
-
gem 'adrian'
|
12
|
-
|
13
|
-
And then execute:
|
14
|
-
|
15
|
-
$ bundle
|
16
|
-
|
17
|
-
Or install it yourself as:
|
18
|
-
|
19
|
-
$ gem install adrian
|
20
|
-
|
21
|
-
## Usage
|
22
|
-
|
23
|
-
TODO: Write usage instructions here
|
24
|
-
|
25
|
-
## Copyright and license
|
26
|
-
|
27
|
-
Copyright 2013 Zendesk
|
28
|
-
|
29
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
|
30
|
-
You may obtain a copy of the License at
|
31
|
-
|
32
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
33
|
-
|
34
|
-
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
data/test/array_queue_test.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
describe Adrian::ArrayQueue do
|
4
|
-
it 'should allow construction with an array' do
|
5
|
-
q = Adrian::ArrayQueue.new([1,2,3])
|
6
|
-
q.pop.value.must_equal 1
|
7
|
-
q.pop.value.must_equal 2
|
8
|
-
q.pop.value.must_equal 3
|
9
|
-
q.pop.must_be_nil
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should allow construction without an array' do
|
13
|
-
q = Adrian::ArrayQueue.new
|
14
|
-
q.pop.must_be_nil
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'should act as a queue' do
|
18
|
-
q = Adrian::ArrayQueue.new
|
19
|
-
|
20
|
-
q.push(1)
|
21
|
-
q.push(2)
|
22
|
-
q.push(3)
|
23
|
-
|
24
|
-
q.length.must_equal 3
|
25
|
-
|
26
|
-
q.pop.value.must_equal 1
|
27
|
-
q.pop.value.must_equal 2
|
28
|
-
q.pop.value.must_equal 3
|
29
|
-
q.pop.must_be_nil
|
30
|
-
|
31
|
-
q.length.must_equal 0
|
32
|
-
end
|
33
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
describe Adrian::CompositeQueue do
|
4
|
-
before do
|
5
|
-
@q1 = Adrian::ArrayQueue.new
|
6
|
-
@q2 = Adrian::ArrayQueue.new
|
7
|
-
@q = Adrian::CompositeQueue.new(@q1, @q2)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "popping" do
|
11
|
-
it 'should return nil when all queues are empty' do
|
12
|
-
@q.pop.must_be_nil
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should return an item from the first queue that has items' do
|
16
|
-
@q1.push(1)
|
17
|
-
@q1.push(2)
|
18
|
-
@q2.push(3)
|
19
|
-
@q2.push(4)
|
20
|
-
|
21
|
-
@q.pop.value.must_equal(1)
|
22
|
-
@q.pop.value.must_equal(2)
|
23
|
-
@q.pop.value.must_equal(3)
|
24
|
-
@q.pop.value.must_equal(4)
|
25
|
-
@q.pop.must_be_nil
|
26
|
-
@q1.pop.must_be_nil
|
27
|
-
@q2.pop.must_be_nil
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'sets the original queue on the item' do
|
31
|
-
@q1.push(1)
|
32
|
-
@q2.push(2)
|
33
|
-
|
34
|
-
@q.pop.queue.must_equal @q1
|
35
|
-
@q.pop.queue.must_equal @q2
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "pushing" do
|
40
|
-
it "should not be allowed" do
|
41
|
-
lambda { @q.push(1) }.must_raise(RuntimeError)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
require 'tempfile'
|
3
|
-
require 'tmpdir'
|
4
|
-
require 'fileutils'
|
5
|
-
require 'logger'
|
6
|
-
|
7
|
-
describe Adrian::DirectoryQueue do
|
8
|
-
before do
|
9
|
-
@logger = Logger.new('/dev/null')
|
10
|
-
@q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'), :delay => 0, :logger => @logger)
|
11
|
-
end
|
12
|
-
|
13
|
-
after do
|
14
|
-
FileUtils.rm_r(@q.available_path, :force => true)
|
15
|
-
FileUtils.rm_r(@q.reserved_path, :force => true)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'should act as a queue for files' do
|
19
|
-
item1 = Tempfile.new('item1-').path
|
20
|
-
item2 = Tempfile.new('item2-').path
|
21
|
-
item3 = Tempfile.new('item3-').path
|
22
|
-
|
23
|
-
@q.push(item1)
|
24
|
-
@q.push(item2)
|
25
|
-
@q.push(item3)
|
26
|
-
|
27
|
-
@q.length.must_equal 3
|
28
|
-
|
29
|
-
@q.pop.must_equal Adrian::FileItem.new(item1)
|
30
|
-
@q.pop.must_equal Adrian::FileItem.new(item2)
|
31
|
-
@q.pop.must_equal Adrian::FileItem.new(item3)
|
32
|
-
@q.pop.must_be_nil
|
33
|
-
|
34
|
-
@q.length.must_equal 0
|
35
|
-
end
|
36
|
-
|
37
|
-
describe 'file backend' do
|
38
|
-
|
39
|
-
describe 'pop' do
|
40
|
-
before do
|
41
|
-
@item = Adrian::FileItem.new(Tempfile.new('item').path)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'provides an available file' do
|
45
|
-
@q.push(@item)
|
46
|
-
assert_equal @item, @q.pop
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'moves the file to the reserved directory' do
|
50
|
-
@q.push(@item)
|
51
|
-
original_path = @item.path
|
52
|
-
item = @q.pop
|
53
|
-
assert_equal @item, item
|
54
|
-
|
55
|
-
assert_equal false, File.exist?(original_path)
|
56
|
-
assert_equal true, File.exist?(File.join(@q.reserved_path, @item.name))
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'reserves the file for an hour by default' do
|
60
|
-
@q.push(@item)
|
61
|
-
reserved_item = @q.pop
|
62
|
-
assert reserved_item
|
63
|
-
one_hour = 3_600
|
64
|
-
|
65
|
-
Time.stub(:now, reserved_item.updated_at + one_hour - 1) do
|
66
|
-
assert_equal nil, @q.pop
|
67
|
-
end
|
68
|
-
|
69
|
-
Time.stub(:now, reserved_item.updated_at + one_hour) do
|
70
|
-
assert_equal @item, @q.pop
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'touches the item' do
|
76
|
-
@q.push(@item)
|
77
|
-
now = Time.now + 100
|
78
|
-
item = nil
|
79
|
-
Time.stub(:now, now) { item = @q.pop }
|
80
|
-
|
81
|
-
assert_equal now.to_i, item.updated_at.to_i
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'skips the file when moved by another process' do
|
85
|
-
def @q.files
|
86
|
-
[ 'no/longer/exists' ]
|
87
|
-
end
|
88
|
-
assert_equal nil, @q.pop
|
89
|
-
end
|
90
|
-
|
91
|
-
it "only provides normal files" do
|
92
|
-
not_file = Dir.mktmpdir(@q.available_path, 'directory_queue_x')
|
93
|
-
assert_equal nil, @q.pop
|
94
|
-
end
|
95
|
-
|
96
|
-
it "set's the logger on the item" do
|
97
|
-
@item.logger.must_be_nil
|
98
|
-
@q.push(@item)
|
99
|
-
@q.pop.logger.must_equal @logger
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
describe 'push' do
|
105
|
-
before do
|
106
|
-
@item = Adrian::FileItem.new(Tempfile.new('item').path)
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'moves the file to the available directory' do
|
110
|
-
original_path = @item.path
|
111
|
-
@q.push(@item)
|
112
|
-
|
113
|
-
assert_equal false, File.exist?(original_path)
|
114
|
-
assert_equal true, File.exist?(File.join(@q.available_path, @item.name))
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'touches the item' do
|
118
|
-
now = Time.now - 100
|
119
|
-
Time.stub(:now, now) { @q.push(@item) }
|
120
|
-
|
121
|
-
assert_equal now.to_i, @item.updated_at.to_i
|
122
|
-
end
|
123
|
-
|
124
|
-
end
|
125
|
-
|
126
|
-
describe 'filters' do
|
127
|
-
it 'should add a delay filter if the :delay option is given' do
|
128
|
-
q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'))
|
129
|
-
filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::Delay)}
|
130
|
-
filter.must_equal nil
|
131
|
-
|
132
|
-
q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'), :delay => 300)
|
133
|
-
filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::Delay)}
|
134
|
-
filter.wont_equal nil
|
135
|
-
filter.duration.must_equal 300
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'should add a lock filter that can be configured with the :lock_duration option' do
|
139
|
-
q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'))
|
140
|
-
filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::FileLock)}
|
141
|
-
filter.wont_equal nil
|
142
|
-
filter.duration.must_equal 3600 # default value
|
143
|
-
|
144
|
-
q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'), :lock_duration => 300)
|
145
|
-
filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::FileLock)}
|
146
|
-
filter.wont_equal nil
|
147
|
-
filter.duration.must_equal 300
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
describe "Adrian::Dispatcher lifecycle" do
|
4
|
-
class Worker < Adrian::Worker
|
5
|
-
def work
|
6
|
-
$done_items << item.value
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
before do
|
11
|
-
$done_items = []
|
12
|
-
@q = Adrian::ArrayQueue.new([1,2,3])
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "stop_when_done" do
|
16
|
-
describe "set to true" do
|
17
|
-
before do
|
18
|
-
@dispatcher = Adrian::Dispatcher.new(:stop_when_done => true)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should have all the work done and stop" do
|
22
|
-
t = Thread.new do
|
23
|
-
@dispatcher.start(@q, Worker)
|
24
|
-
end
|
25
|
-
|
26
|
-
sleep(0.5)
|
27
|
-
|
28
|
-
@q.pop.must_be_nil
|
29
|
-
|
30
|
-
$done_items.must_equal([1,2,3])
|
31
|
-
|
32
|
-
@dispatcher.running.must_equal false
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "set to false" do
|
37
|
-
before do
|
38
|
-
@dispatcher = Adrian::Dispatcher.new(:stop_when_done => false)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should have all the work done and continue" do
|
42
|
-
t = Thread.new do
|
43
|
-
@dispatcher.start(@q, Worker)
|
44
|
-
end
|
45
|
-
|
46
|
-
sleep(0.5)
|
47
|
-
|
48
|
-
@q.pop.must_be_nil
|
49
|
-
|
50
|
-
$done_items.must_equal([1,2,3])
|
51
|
-
|
52
|
-
@dispatcher.running.must_equal true
|
53
|
-
t.kill
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "#stop" do
|
59
|
-
before do
|
60
|
-
@dispatcher = Adrian::Dispatcher.new(:sleep => 0.1)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "should stop a running dispatcher" do
|
64
|
-
t = Thread.new do
|
65
|
-
@dispatcher.start(@q, Worker)
|
66
|
-
end
|
67
|
-
|
68
|
-
sleep(0.5)
|
69
|
-
|
70
|
-
@dispatcher.running.must_equal true
|
71
|
-
t.status.wont_equal false
|
72
|
-
|
73
|
-
@dispatcher.stop
|
74
|
-
|
75
|
-
sleep(0.5)
|
76
|
-
|
77
|
-
@dispatcher.running.must_equal false
|
78
|
-
t.status.must_equal false
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
data/test/dispatcher_test.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
describe Adrian::Dispatcher do
|
4
|
-
before do
|
5
|
-
$done_items = []
|
6
|
-
@q = Adrian::ArrayQueue.new([], :max_age => 1000)
|
7
|
-
@dispatcher = Adrian::Dispatcher.new(:stop_when_done => true)
|
8
|
-
@worker = TestWorker
|
9
|
-
end
|
10
|
-
|
11
|
-
class TestWorker
|
12
|
-
|
13
|
-
def initialize(item)
|
14
|
-
@item = item
|
15
|
-
@done_items = []
|
16
|
-
end
|
17
|
-
|
18
|
-
def perform
|
19
|
-
$done_items << @item.value
|
20
|
-
end
|
21
|
-
|
22
|
-
def report_to(boss)
|
23
|
-
@boss = boss
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "work delegation" do
|
29
|
-
it "should instantiate an instance of the worker for each item and ask it to perform" do
|
30
|
-
@q.push(1)
|
31
|
-
@q.push(2)
|
32
|
-
@q.push(3)
|
33
|
-
|
34
|
-
@dispatcher.start(@q, @worker)
|
35
|
-
|
36
|
-
$done_items.must_equal([1, 2, 3])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "a queue with old items" do
|
41
|
-
before do
|
42
|
-
@q.push(Adrian::QueueItem.new(1, Time.now))
|
43
|
-
@old_item = Adrian::QueueItem.new(2, Time.now - 2000)
|
44
|
-
@q.push(@old_item)
|
45
|
-
@q.push(Adrian::QueueItem.new(3, Time.now))
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'skips the old items' do
|
49
|
-
@dispatcher.start(@q, @worker)
|
50
|
-
|
51
|
-
$done_items.must_equal([1, 3])
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'calls the handler for Adrian::Queue::ItemTooOldError' do
|
55
|
-
handled_items = []
|
56
|
-
handled_exceptions = []
|
57
|
-
|
58
|
-
@dispatcher.on_failure(Adrian::Queue::ItemTooOldError) do |item, worker, exception|
|
59
|
-
handled_items << item
|
60
|
-
handled_exceptions << exception
|
61
|
-
end
|
62
|
-
|
63
|
-
@dispatcher.start(@q, @worker)
|
64
|
-
|
65
|
-
handled_items.must_equal [@old_item]
|
66
|
-
handled_exceptions.size.must_equal 1
|
67
|
-
handled_exceptions.first.must_be_instance_of Adrian::Queue::ItemTooOldError
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "work evaluation" do
|
72
|
-
|
73
|
-
it "stops when receiving a termination signal" do
|
74
|
-
@dispatcher = Adrian::Dispatcher.new(:stop_when_done => false)
|
75
|
-
dispatch_thread = Thread.new { @dispatcher.start(@q, @worker) }
|
76
|
-
sleep(0.1)
|
77
|
-
assert_equal true, @dispatcher.running
|
78
|
-
|
79
|
-
Process.kill('TERM', Process.pid)
|
80
|
-
assert_equal false, @dispatcher.running
|
81
|
-
dispatch_thread.exit
|
82
|
-
end
|
83
|
-
|
84
|
-
it "should use the failure handler to handle the result" do
|
85
|
-
@dispatcher.on_failure(RuntimeError) do |item, worker, exception|
|
86
|
-
@q.push(item)
|
87
|
-
end
|
88
|
-
|
89
|
-
@dispatcher.work_done(1, nil)
|
90
|
-
@q.pop.must_be_nil
|
91
|
-
|
92
|
-
@dispatcher.work_done(1, nil, nil)
|
93
|
-
@q.pop.must_be_nil
|
94
|
-
|
95
|
-
@dispatcher.work_done(1, nil, RuntimeError.new)
|
96
|
-
@q.pop.value.must_equal 1
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
require 'adrian/failure_handler'
|
4
|
-
|
5
|
-
describe Adrian::FailureHandler do
|
6
|
-
before do
|
7
|
-
@handler = Adrian::FailureHandler.new
|
8
|
-
|
9
|
-
$failure = nil
|
10
|
-
|
11
|
-
@handler.add_rule(RuntimeError) { :runtime }
|
12
|
-
@handler.add_rule(StandardError) { :standard }
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should match rules in the order they were added" do
|
16
|
-
block = @handler.handle(RuntimeError.new)
|
17
|
-
assert block
|
18
|
-
block.call.must_equal :runtime
|
19
|
-
|
20
|
-
block = @handler.handle(StandardError.new)
|
21
|
-
assert block
|
22
|
-
block.call.must_equal :standard
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should do nothing when no rules match" do
|
26
|
-
@handler.handle(Exception.new).must_be_nil
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "the success rule" do
|
30
|
-
before do
|
31
|
-
@handler = Adrian::FailureHandler.new
|
32
|
-
@handler.add_rule(nil) { :success }
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should match when there is no exception" do
|
36
|
-
@handler.handle(RuntimeError.new).must_be_nil
|
37
|
-
|
38
|
-
block = @handler.handle(nil)
|
39
|
-
assert block
|
40
|
-
block.call.must_equal :success
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
data/test/file_item_test.rb
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
require 'tempfile'
|
3
|
-
|
4
|
-
describe Adrian::FileItem do
|
5
|
-
before do
|
6
|
-
@item = Adrian::FileItem.new(Tempfile.new('file_item_test').path)
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'aliases value as path' do
|
10
|
-
item = Adrian::FileItem.new('path/a')
|
11
|
-
assert_equal 'path/a', item.value
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'has a name from the path' do
|
15
|
-
item = Adrian::FileItem.new('path/name.ext')
|
16
|
-
assert_equal 'name.ext', item.name
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'is equal to another item when they have the same name' do
|
20
|
-
item1 = Adrian::FileItem.new('path/a')
|
21
|
-
item2 = Adrian::FileItem.new('path/b')
|
22
|
-
assert(item1 != item2)
|
23
|
-
|
24
|
-
item3 = Adrian::FileItem.new('path/a')
|
25
|
-
assert_equal item1, item3
|
26
|
-
end
|
27
|
-
|
28
|
-
describe 'updated_at' do
|
29
|
-
|
30
|
-
it 'is the atime of the file' do
|
31
|
-
@item.updated_at.must_equal File.atime(@item.path)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'is nil when moved by another process' do
|
35
|
-
item = Adrian::FileItem.new('moved/during/initialize')
|
36
|
-
assert_equal false, item.exist?
|
37
|
-
assert_equal nil, item.updated_at
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'is cached' do
|
41
|
-
updated_at = @item.updated_at
|
42
|
-
assert @item.updated_at
|
43
|
-
File.unlink(@item.path)
|
44
|
-
assert_equal false, @item.exist?
|
45
|
-
|
46
|
-
assert_equal updated_at, @item.updated_at
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
describe 'created_at' do
|
52
|
-
|
53
|
-
it 'is the mtime of the file' do
|
54
|
-
@item.created_at.must_equal File.mtime(@item.path)
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'is nil when moved by another process' do
|
58
|
-
item = Adrian::FileItem.new('moved/during/initialize')
|
59
|
-
assert_equal false, item.exist?
|
60
|
-
assert_equal nil, item.created_at
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'is cached' do
|
64
|
-
created_at = @item.created_at
|
65
|
-
assert @item.created_at
|
66
|
-
File.unlink(@item.path)
|
67
|
-
assert_equal false, @item.exist?
|
68
|
-
|
69
|
-
assert_equal created_at, @item.created_at
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
describe 'move' do
|
75
|
-
before do
|
76
|
-
@destination = Dir.mktmpdir('file_item_move_test')
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'moves the file to the given directory' do
|
80
|
-
@item.move(@destination)
|
81
|
-
assert_equal true, File.exist?(File.join(@destination, @item.name))
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'updates the path to its new location' do
|
85
|
-
@item.move(@destination)
|
86
|
-
assert_equal @destination, File.dirname(@item.path)
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'logs the move on the logger' do
|
90
|
-
destination_file_name = File.join(@destination, File.basename(@item.path))
|
91
|
-
logger = MiniTest::Mock.new
|
92
|
-
logger.expect(:info, nil, ["Moving #{@item.path} to #{destination_file_name}"])
|
93
|
-
@item.logger = logger
|
94
|
-
|
95
|
-
@item.move(@destination)
|
96
|
-
|
97
|
-
logger.verify
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'does not change the atime' do
|
101
|
-
atime = File.atime(@item.path)
|
102
|
-
@item.move(@destination)
|
103
|
-
File.atime(@item.path).must_equal atime
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'does not change the mtime' do
|
107
|
-
mtime = File.mtime(@item.path)
|
108
|
-
@item.move(@destination)
|
109
|
-
File.mtime(@item.path).must_equal mtime
|
110
|
-
end
|
111
|
-
|
112
|
-
end
|
113
|
-
|
114
|
-
describe 'touch' do
|
115
|
-
|
116
|
-
it 'changes the update timestamp to the current time' do
|
117
|
-
now = Time.now - 100
|
118
|
-
Time.stub(:now, now) { @item.touch }
|
119
|
-
|
120
|
-
assert_equal now.to_i, @item.updated_at.to_i
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'changes the atime' do
|
124
|
-
atime = File.atime(@item.path).to_i
|
125
|
-
|
126
|
-
now = (Time.now - 100)
|
127
|
-
Time.stub(:now, now) { @item.touch }
|
128
|
-
|
129
|
-
now.to_i.wont_equal atime
|
130
|
-
File.atime(@item.path).to_i.must_equal now.to_i
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'does not change the mtime' do
|
134
|
-
mtime = File.mtime(@item.path).to_i
|
135
|
-
|
136
|
-
now = (Time.now - 100)
|
137
|
-
Time.stub(:new, now) { @item.touch }
|
138
|
-
|
139
|
-
now.to_i.wont_equal mtime
|
140
|
-
File.mtime(@item.path).to_i.must_equal mtime
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'exists when the file at the given path exists' do
|
146
|
-
assert_equal true, @item.exist?
|
147
|
-
File.unlink(@item.path)
|
148
|
-
|
149
|
-
assert_equal false, @item.exist?
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
data/test/filters_test.rb
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
require 'tempfile'
|
3
|
-
require 'tmpdir'
|
4
|
-
|
5
|
-
|
6
|
-
describe Adrian::Filters do
|
7
|
-
before do
|
8
|
-
@q = Object.new.extend(Adrian::Filters)
|
9
|
-
@item = Adrian::QueueItem.new("hello")
|
10
|
-
end
|
11
|
-
|
12
|
-
class FakeFilter
|
13
|
-
|
14
|
-
def initialize(options = {})
|
15
|
-
@allow = options.fetch(:allow)
|
16
|
-
end
|
17
|
-
|
18
|
-
def allow?(item)
|
19
|
-
@allow == true
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "#filter?" do
|
25
|
-
|
26
|
-
it "is true when any filter denies the item" do
|
27
|
-
@q.filters << FakeFilter.new(:allow => true)
|
28
|
-
@q.filters << FakeFilter.new(:allow => false)
|
29
|
-
|
30
|
-
assert_equal true, @q.filter?(@item)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "is false when all filters allow the item" do
|
34
|
-
@q.filters << FakeFilter.new(:allow => true)
|
35
|
-
assert_equal false, @q.filter?(@item)
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
module Updatable
|
41
|
-
attr_accessor :updated_at
|
42
|
-
end
|
43
|
-
|
44
|
-
describe Adrian::Filters::Delay do
|
45
|
-
before do
|
46
|
-
@filter = Adrian::Filters::Delay.new
|
47
|
-
@updatable_item = Adrian::QueueItem.new("hello")
|
48
|
-
@updatable_item.extend(Updatable)
|
49
|
-
@updatable_item.updated_at = Time.now
|
50
|
-
@fifteen_minutes = 900
|
51
|
-
end
|
52
|
-
|
53
|
-
it "allows items that have not been recently updated" do
|
54
|
-
Time.stub(:now, @updatable_item.updated_at + @fifteen_minutes) do
|
55
|
-
assert_equal true, @filter.allow?(@updatable_item)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
it "denies items that have been recently updated" do
|
60
|
-
assert_equal false, @filter.allow?(@updatable_item)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "has a configurable recently updated duration that defaults to 15 minutes" do
|
64
|
-
assert_equal @fifteen_minutes, @filter.duration
|
65
|
-
configured_filter = Adrian::Filters::Delay.new(:duration => 1)
|
66
|
-
|
67
|
-
assert_equal 1, configured_filter.duration
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
describe Adrian::Filters::FileLock do
|
73
|
-
before do
|
74
|
-
@filter = Adrian::Filters::FileLock.new(:reserved_path => 'path/to/locked')
|
75
|
-
@available_item = Adrian::FileItem.new("path/to/file")
|
76
|
-
@locked_item = Adrian::FileItem.new("path/to/locked/file")
|
77
|
-
@one_hour = 3_600
|
78
|
-
end
|
79
|
-
|
80
|
-
it "allows items that are not locked" do
|
81
|
-
assert_equal true, @filter.allow?(@available_item)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "allows items with an expired lock" do
|
85
|
-
@locked_item.stub(:updated_at, Time.now - @one_hour) do
|
86
|
-
assert_equal true, @filter.allow?(@locked_item)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
it "does not allow items with a fresh lock" do
|
91
|
-
@locked_item.stub(:updated_at, Time.now) do
|
92
|
-
assert_equal false, @filter.allow?(@locked_item)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
it "has a configurable lock expiry duration that defaults to one hour" do
|
97
|
-
assert_equal @one_hour, @filter.duration
|
98
|
-
configured_filter = Adrian::Filters::FileLock.new(:duration => 1, :reserved_path => 'path/to/locked')
|
99
|
-
|
100
|
-
assert_equal 1, configured_filter.duration
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
|
105
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
describe Adrian::GirlFridayDispatcher do
|
4
|
-
before do
|
5
|
-
$done_items = []
|
6
|
-
@q = Adrian::ArrayQueue.new
|
7
|
-
@dispatcher = Adrian::GirlFridayDispatcher.new(:stop_when_done => true)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "work delegation" do
|
11
|
-
it "should instantiate an instance of the worker for each item and ask it to perform" do
|
12
|
-
worker = Class.new(Adrian::Worker) do
|
13
|
-
def work
|
14
|
-
sleep(rand)
|
15
|
-
$done_items << @item.value
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
@q.push(1)
|
20
|
-
@q.push(2)
|
21
|
-
@q.push(3)
|
22
|
-
|
23
|
-
@dispatcher.start(@q, worker)
|
24
|
-
|
25
|
-
$done_items.sort.must_equal([1, 2, 3])
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/test/queue_test.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
describe Adrian::Queue do
|
4
|
-
class TestQueue < Adrian::Queue
|
5
|
-
attr_accessor :item
|
6
|
-
|
7
|
-
def pop_item
|
8
|
-
@item
|
9
|
-
end
|
10
|
-
|
11
|
-
def push_item(item)
|
12
|
-
@item = item
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe 'when a max age is defined' do
|
17
|
-
before { @q = TestQueue.new(:max_age => 60) }
|
18
|
-
|
19
|
-
it 'validates the age of items' do
|
20
|
-
item = Adrian::QueueItem.new('value', Time.now)
|
21
|
-
@q.push(item)
|
22
|
-
@q.pop.must_equal item
|
23
|
-
|
24
|
-
item = Adrian::QueueItem.new('value', Time.now - 120)
|
25
|
-
@q.push(item)
|
26
|
-
lambda { @q.pop }.must_raise(Adrian::Queue::ItemTooOldError)
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'sets the queue on the items' do
|
32
|
-
q = TestQueue.new
|
33
|
-
|
34
|
-
item = Adrian::QueueItem.new('value', Time.now)
|
35
|
-
|
36
|
-
item.queue.must_be_nil
|
37
|
-
|
38
|
-
q.push(item)
|
39
|
-
|
40
|
-
item.queue.must_be_nil
|
41
|
-
|
42
|
-
popped_item = q.pop
|
43
|
-
|
44
|
-
popped_item.must_equal item
|
45
|
-
item.queue.must_equal q
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
require 'tempfile'
|
3
|
-
require 'tmpdir'
|
4
|
-
require 'fileutils'
|
5
|
-
|
6
|
-
describe Adrian::RotatingDirectoryQueue do
|
7
|
-
before do
|
8
|
-
@root_path = Dir.mktmpdir('dir_queue_test')
|
9
|
-
@q = Adrian::RotatingDirectoryQueue.create(:path => @root_path)
|
10
|
-
Timecop.freeze
|
11
|
-
end
|
12
|
-
|
13
|
-
after do
|
14
|
-
Timecop.return
|
15
|
-
FileUtils.rm_r(@root_path, :force => true)
|
16
|
-
end
|
17
|
-
|
18
|
-
describe 'pop' do
|
19
|
-
it 'only provides files available in the current time-stamped directory' do
|
20
|
-
@item1 = Adrian::FileItem.new(Tempfile.new('item1').path)
|
21
|
-
@item2 = Adrian::FileItem.new(Tempfile.new('item2').path)
|
22
|
-
@item3 = Adrian::FileItem.new(Tempfile.new('item3').path)
|
23
|
-
|
24
|
-
todays_directory = File.join(@root_path, Time.now.strftime('%Y-%m-%d'))
|
25
|
-
tomorrows_directory = File.join(@root_path, (Time.now + 60 * 60 * 24).strftime('%Y-%m-%d'))
|
26
|
-
|
27
|
-
FileUtils.mkdir_p(todays_directory)
|
28
|
-
FileUtils.mkdir_p(tomorrows_directory)
|
29
|
-
|
30
|
-
@item1.move(todays_directory)
|
31
|
-
@item2.move(tomorrows_directory)
|
32
|
-
@item3.move(@root_path)
|
33
|
-
|
34
|
-
@q.pop.must_equal @item1
|
35
|
-
@q.pop.must_be_nil
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe 'push' do
|
40
|
-
before do
|
41
|
-
@item = Adrian::FileItem.new(Tempfile.new('item').path)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'moves the file to the time-stamped available directory' do
|
45
|
-
original_path = @item.path
|
46
|
-
@q.push(@item)
|
47
|
-
|
48
|
-
assert_equal false, File.exist?(original_path)
|
49
|
-
assert_equal true, File.exist?(File.join(@q.available_path, @item.name))
|
50
|
-
|
51
|
-
@item.path.must_equal File.join(@root_path, Time.now.strftime('%Y-%m-%d'), @item.name)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
data/test/test_helper.rb
DELETED
data/test/worker_test.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
describe Adrian::Worker do
|
4
|
-
describe "#perform" do
|
5
|
-
before { @item = 2}
|
6
|
-
|
7
|
-
it "should report back to the boss" do
|
8
|
-
worker_class = Class.new(Adrian::Worker) do
|
9
|
-
def work; item + 2; end
|
10
|
-
end
|
11
|
-
|
12
|
-
worker = worker_class.new(@item)
|
13
|
-
boss = MiniTest::Mock.new
|
14
|
-
worker.report_to(boss)
|
15
|
-
|
16
|
-
boss.expect(:work_done, nil, [@item, worker, nil])
|
17
|
-
worker.perform
|
18
|
-
|
19
|
-
boss.verify
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should NEVER raise an exception" do
|
23
|
-
worker_class = Class.new(Adrian::Worker) do
|
24
|
-
def work; raise "STRIKE!"; end
|
25
|
-
end
|
26
|
-
|
27
|
-
worker = worker_class.new(@item)
|
28
|
-
boss = MiniTest::Mock.new
|
29
|
-
worker.report_to(boss)
|
30
|
-
|
31
|
-
boss.expect(:work_done, nil, [@item, worker, RuntimeError])
|
32
|
-
|
33
|
-
worker.perform
|
34
|
-
|
35
|
-
boss.verify
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|