pigeon 0.3.0 → 0.4.0
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.
- data/README.rdoc +36 -60
- data/Rakefile +1 -14
- data/VERSION +1 -1
- data/bin/launcher.example +15 -0
- data/lib/pigeon/dispatcher.rb +93 -0
- data/lib/pigeon/engine.rb +36 -27
- data/lib/pigeon/option_accessor.rb +2 -0
- data/lib/pigeon/processor.rb +66 -0
- data/lib/pigeon/queue.rb +269 -36
- data/lib/pigeon/scheduler.rb +101 -0
- data/lib/pigeon/sorted_array.rb +56 -0
- data/lib/pigeon/support.rb +15 -0
- data/lib/pigeon/task.rb +188 -0
- data/lib/pigeon.rb +9 -1
- data/pigeon.gemspec +29 -12
- data/test/helper.rb +19 -0
- data/test/unit/pigeon_backlog_test.rb +25 -0
- data/test/unit/pigeon_dispatcher_test.rb +62 -0
- data/test/{test_pigeon_engine.rb → unit/pigeon_engine_test.rb} +1 -1
- data/test/{test_pigeon_launcher.rb → unit/pigeon_launcher_test.rb} +1 -1
- data/test/{test_pigeon_option_accessor.rb → unit/pigeon_option_accessor_test.rb} +1 -1
- data/test/unit/pigeon_processor_test.rb +94 -0
- data/test/unit/pigeon_queue_test.rb +197 -0
- data/test/unit/pigeon_scheduler_test.rb +70 -0
- data/test/unit/pigeon_sorted_array_test.rb +52 -0
- data/test/unit/pigeon_task_test.rb +164 -0
- data/test/{test_pigeon.rb → unit/pigeon_test.rb} +1 -1
- metadata +30 -13
- data/test/test_pigeon_queue.rb +0 -29
data/lib/pigeon.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
module Pigeon
|
2
2
|
# == Autoloads ============================================================
|
3
3
|
|
4
|
+
autoload(:Backlog, 'pigeon/backlog')
|
5
|
+
autoload(:Dispatcher, 'pigeon/dispatcher')
|
4
6
|
autoload(:Engine, 'pigeon/engine')
|
5
7
|
autoload(:Launcher, 'pigeon/launcher')
|
6
8
|
autoload(:OptionAccessor, 'pigeon/option_accessor')
|
7
9
|
autoload(:Pidfile, 'pigeon/pidfile')
|
10
|
+
autoload(:Processor, 'pigeon/processor')
|
8
11
|
autoload(:Queue, 'pigeon/queue')
|
12
|
+
autoload(:Scheduler, 'pigeon/scheduler')
|
13
|
+
autoload(:SortedArray, 'pigeon/sorted_array')
|
9
14
|
autoload(:Support, 'pigeon/support')
|
15
|
+
autoload(:Task, 'pigeon/task')
|
10
16
|
end
|
11
17
|
|
12
|
-
|
18
|
+
# NOTE: This file needs to be directly loaded due to some kind of peculiar
|
19
|
+
# issue where requiring it later causes a run-time Interrupt exception.
|
20
|
+
require 'pigeon/logger'
|
data/pigeon.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{pigeon}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["tadman"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-11-09}
|
13
13
|
s.default_executable = %q{launcher.example}
|
14
14
|
s.description = %q{Pigeon is a simple way to get started building an EventMachine engine that's intended to run as a background job.}
|
15
15
|
s.email = %q{github@tadman.ca}
|
@@ -27,20 +27,31 @@ Gem::Specification.new do |s|
|
|
27
27
|
"VERSION",
|
28
28
|
"bin/launcher.example",
|
29
29
|
"lib/pigeon.rb",
|
30
|
+
"lib/pigeon/dispatcher.rb",
|
30
31
|
"lib/pigeon/engine.rb",
|
31
32
|
"lib/pigeon/launcher.rb",
|
32
33
|
"lib/pigeon/logger.rb",
|
33
34
|
"lib/pigeon/option_accessor.rb",
|
34
35
|
"lib/pigeon/pidfile.rb",
|
36
|
+
"lib/pigeon/processor.rb",
|
35
37
|
"lib/pigeon/queue.rb",
|
38
|
+
"lib/pigeon/scheduler.rb",
|
39
|
+
"lib/pigeon/sorted_array.rb",
|
36
40
|
"lib/pigeon/support.rb",
|
41
|
+
"lib/pigeon/task.rb",
|
37
42
|
"pigeon.gemspec",
|
38
43
|
"test/helper.rb",
|
39
|
-
"test/
|
40
|
-
"test/
|
41
|
-
"test/
|
42
|
-
"test/
|
43
|
-
"test/
|
44
|
+
"test/unit/pigeon_backlog_test.rb",
|
45
|
+
"test/unit/pigeon_dispatcher_test.rb",
|
46
|
+
"test/unit/pigeon_engine_test.rb",
|
47
|
+
"test/unit/pigeon_launcher_test.rb",
|
48
|
+
"test/unit/pigeon_option_accessor_test.rb",
|
49
|
+
"test/unit/pigeon_processor_test.rb",
|
50
|
+
"test/unit/pigeon_queue_test.rb",
|
51
|
+
"test/unit/pigeon_scheduler_test.rb",
|
52
|
+
"test/unit/pigeon_sorted_array_test.rb",
|
53
|
+
"test/unit/pigeon_task_test.rb",
|
54
|
+
"test/unit/pigeon_test.rb"
|
44
55
|
]
|
45
56
|
s.homepage = %q{http://github.com/tadman/pigeon}
|
46
57
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -49,11 +60,17 @@ Gem::Specification.new do |s|
|
|
49
60
|
s.summary = %q{Simple daemonized EventMachine engine framework with plug-in support}
|
50
61
|
s.test_files = [
|
51
62
|
"test/helper.rb",
|
52
|
-
"test/
|
53
|
-
"test/
|
54
|
-
"test/
|
55
|
-
"test/
|
56
|
-
"test/
|
63
|
+
"test/unit/pigeon_backlog_test.rb",
|
64
|
+
"test/unit/pigeon_dispatcher_test.rb",
|
65
|
+
"test/unit/pigeon_engine_test.rb",
|
66
|
+
"test/unit/pigeon_launcher_test.rb",
|
67
|
+
"test/unit/pigeon_option_accessor_test.rb",
|
68
|
+
"test/unit/pigeon_processor_test.rb",
|
69
|
+
"test/unit/pigeon_queue_test.rb",
|
70
|
+
"test/unit/pigeon_scheduler_test.rb",
|
71
|
+
"test/unit/pigeon_sorted_array_test.rb",
|
72
|
+
"test/unit/pigeon_task_test.rb",
|
73
|
+
"test/unit/pigeon_test.rb"
|
57
74
|
]
|
58
75
|
|
59
76
|
if s.respond_to? :specification_version then
|
data/test/helper.rb
CHANGED
@@ -4,6 +4,8 @@ require 'test/unit'
|
|
4
4
|
$LOAD_PATH.unshift(File.expand_path(*%w[ .. lib ]), File.dirname(__FILE__))
|
5
5
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
6
|
|
7
|
+
require 'timeout'
|
8
|
+
|
7
9
|
require 'rubygems'
|
8
10
|
|
9
11
|
if (Gem.available?('eventmachine'))
|
@@ -15,4 +17,21 @@ end
|
|
15
17
|
require 'pigeon'
|
16
18
|
|
17
19
|
class Test::Unit::TestCase
|
20
|
+
def assert_timeout(time, message = nil, &block)
|
21
|
+
Timeout::timeout(time, &block)
|
22
|
+
rescue Timeout::Error
|
23
|
+
flunk(message || 'assert_timeout timed out')
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_eventually(time = nil, message = nil, &block)
|
27
|
+
start_time = Time.now.to_i
|
28
|
+
|
29
|
+
while (!block.call)
|
30
|
+
select(nil, nil, nil, 0.1)
|
31
|
+
|
32
|
+
if (time and (Time.now.to_i - start_time > time))
|
33
|
+
flunk(message || 'assert_eventually timed out')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
18
37
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class PigeonQueueTest < Test::Unit::TestCase
|
4
|
+
def test_empty_queue
|
5
|
+
queue = Pigeon::Queue.new
|
6
|
+
|
7
|
+
assert queue.empty?
|
8
|
+
assert_equal 0, queue.length
|
9
|
+
|
10
|
+
assert_equal nil, queue.pop
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_queue_cycling
|
14
|
+
queue = Pigeon::Queue.new
|
15
|
+
|
16
|
+
task = Pigeon::Task.new
|
17
|
+
|
18
|
+
queue << task
|
19
|
+
|
20
|
+
assert_equal 1, queue.length
|
21
|
+
assert !queue.empty?
|
22
|
+
|
23
|
+
found_task = queue.pop
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class PigeonDispatcherTest < Test::Unit::TestCase
|
4
|
+
def test_routine_dispatching
|
5
|
+
dispatcher = Pigeon::Dispatcher.new
|
6
|
+
|
7
|
+
assert_equal Pigeon::Dispatcher.thread_limit, dispatcher.thread_limit
|
8
|
+
|
9
|
+
checks = { }
|
10
|
+
|
11
|
+
count = 100
|
12
|
+
|
13
|
+
count.times do |n|
|
14
|
+
dispatcher.perform do
|
15
|
+
x = 0
|
16
|
+
|
17
|
+
1000.times do
|
18
|
+
dispatcher.perform do
|
19
|
+
x += 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
checks[n] = x
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_timeout(10) do
|
28
|
+
dispatcher.wait!
|
29
|
+
end
|
30
|
+
|
31
|
+
assert_equal 0, dispatcher.backlog_size
|
32
|
+
assert_equal 0, dispatcher.thread_count
|
33
|
+
assert dispatcher.empty?
|
34
|
+
assert_equal [ ], dispatcher.exceptions
|
35
|
+
assert !dispatcher.exceptions?
|
36
|
+
|
37
|
+
assert_equal (0..count - 1).to_a, checks.keys.sort
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_dispatch_variants
|
41
|
+
dispatcher = Pigeon::Dispatcher.new
|
42
|
+
|
43
|
+
result = [ ]
|
44
|
+
|
45
|
+
dispatcher.perform do
|
46
|
+
result[0] = :a
|
47
|
+
end
|
48
|
+
|
49
|
+
dispatcher.perform(:b) do |b|
|
50
|
+
result[1] = b
|
51
|
+
end
|
52
|
+
|
53
|
+
dispatcher.perform(:c, :d) do |c, d|
|
54
|
+
result[2] = c
|
55
|
+
result[3] = d
|
56
|
+
end
|
57
|
+
|
58
|
+
dispatcher.wait!
|
59
|
+
|
60
|
+
assert_equal [ :a, :b, :c, :d ], result
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class PigeonProcessorTest < Test::Unit::TestCase
|
4
|
+
class TaggedTask < Pigeon::Task
|
5
|
+
attr_accessor :tag
|
6
|
+
|
7
|
+
def initialize(engine, tag)
|
8
|
+
super(engine)
|
9
|
+
@tag = tag
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"<#{@tag}>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def engine
|
18
|
+
@engine ||= Pigeon::Engine.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_empty_processor
|
22
|
+
queue = Pigeon::Queue.new
|
23
|
+
|
24
|
+
processor = Pigeon::Processor.new(queue)
|
25
|
+
|
26
|
+
assert_equal false, processor.task?
|
27
|
+
|
28
|
+
assert_equal true, processor.accept?(Pigeon::Task.new(engine))
|
29
|
+
|
30
|
+
assert processor.id
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_simple_filter
|
34
|
+
queue = Pigeon::Queue.new
|
35
|
+
|
36
|
+
processor = Pigeon::Processor.new(queue) do |task|
|
37
|
+
(task.tag % 2) == 1
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_equal false, processor.task?
|
41
|
+
|
42
|
+
queue << TaggedTask.new(engine, 0)
|
43
|
+
|
44
|
+
assert_equal false, processor.task?
|
45
|
+
assert_equal 1, queue.length
|
46
|
+
|
47
|
+
queue << TaggedTask.new(engine, 1)
|
48
|
+
|
49
|
+
assert_equal true, processor.task?
|
50
|
+
assert_equal 1, queue.length
|
51
|
+
|
52
|
+
assert_eventually(5) do
|
53
|
+
!processor.task?
|
54
|
+
end
|
55
|
+
|
56
|
+
assert_equal 1, queue.length
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_on_backlog
|
60
|
+
queue = Pigeon::Queue.new
|
61
|
+
|
62
|
+
100.times do |n|
|
63
|
+
queue << TaggedTask.new(engine, n)
|
64
|
+
end
|
65
|
+
|
66
|
+
processor = Pigeon::Processor.new(queue)
|
67
|
+
|
68
|
+
assert_eventually(5) do
|
69
|
+
queue.empty?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_multiple_processors
|
74
|
+
queue = Pigeon::Queue.new
|
75
|
+
count = 10000
|
76
|
+
|
77
|
+
count.times do |n|
|
78
|
+
queue << TaggedTask.new(engine, n)
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_equal count, queue.length
|
82
|
+
|
83
|
+
processors = (0..9).to_a.collect do
|
84
|
+
Pigeon::Processor.new(queue)
|
85
|
+
end
|
86
|
+
|
87
|
+
assert_eventually(10) do
|
88
|
+
queue.empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
assert_equal 0, processors.select(&:task?).length
|
92
|
+
assert_equal 0, queue.length
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class PigeonQueueTest < Test::Unit::TestCase
|
4
|
+
class TaggedTask < Pigeon::Task
|
5
|
+
attr_accessor :tag
|
6
|
+
|
7
|
+
def initialize(engine, tag)
|
8
|
+
super(engine)
|
9
|
+
@tag = tag
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"<#{@tag}>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def engine
|
18
|
+
@engine ||= Pigeon::Engine.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_empty_state
|
22
|
+
queue = Pigeon::Queue.new
|
23
|
+
|
24
|
+
assert_equal 0, queue.length
|
25
|
+
assert_equal true, queue.empty?
|
26
|
+
|
27
|
+
assert_equal nil, queue.pop
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_cycling
|
31
|
+
queue = Pigeon::Queue.new
|
32
|
+
|
33
|
+
task = Pigeon::Task.new(engine)
|
34
|
+
|
35
|
+
assert_equal task, queue << task
|
36
|
+
|
37
|
+
assert queue.peek
|
38
|
+
assert_equal 1, queue.length
|
39
|
+
assert !queue.empty?
|
40
|
+
|
41
|
+
found_task = queue.pop
|
42
|
+
|
43
|
+
assert_equal task, found_task
|
44
|
+
|
45
|
+
assert_equal 0, queue.length
|
46
|
+
assert queue.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_filtering
|
50
|
+
queue = Pigeon::Queue.new
|
51
|
+
|
52
|
+
tasks = (0..9).to_a.collect do |n|
|
53
|
+
queue << TaggedTask.new(engine, n)
|
54
|
+
end
|
55
|
+
|
56
|
+
assert_equal (0..9).to_a, tasks.to_a.collect(&:tag)
|
57
|
+
|
58
|
+
assert_equal tasks[0], queue.peek
|
59
|
+
|
60
|
+
selected_task = queue.peek do |task|
|
61
|
+
task.tag > 0
|
62
|
+
end
|
63
|
+
|
64
|
+
assert_equal tasks[1], selected_task
|
65
|
+
|
66
|
+
queue.filter(:over_7) do |task|
|
67
|
+
task.tag > 7
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_equal tasks[8], queue.peek(:over_7)
|
71
|
+
assert_equal 2, queue.length(:over_7)
|
72
|
+
|
73
|
+
pulled_task = queue.pop(:over_7)
|
74
|
+
|
75
|
+
assert_equal 9, queue.length
|
76
|
+
|
77
|
+
assert_equal tasks[9], queue.peek(:over_7)
|
78
|
+
assert_equal 1, queue.length(:over_7)
|
79
|
+
|
80
|
+
queue.pop(:over_7)
|
81
|
+
|
82
|
+
assert_equal nil, queue.peek(:over_7)
|
83
|
+
assert_equal 0, queue.length(:over_7)
|
84
|
+
assert_equal true, queue.empty?(:over_7)
|
85
|
+
|
86
|
+
new_task = queue << TaggedTask.new(engine, 10)
|
87
|
+
|
88
|
+
assert_equal new_task, queue.peek(:over_7)
|
89
|
+
assert_equal 1, queue.length(:over_7)
|
90
|
+
assert_equal false, queue.empty?(:over_7)
|
91
|
+
|
92
|
+
queue.claim(new_task)
|
93
|
+
|
94
|
+
assert_equal nil, queue.peek(:over_7)
|
95
|
+
assert_equal 0, queue.length(:over_7)
|
96
|
+
assert_equal true, queue.empty?(:over_7)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_observe
|
100
|
+
queue = Pigeon::Queue.new
|
101
|
+
|
102
|
+
tasks = (0..9).to_a.collect do |n|
|
103
|
+
queue << TaggedTask.new(engine, n)
|
104
|
+
end
|
105
|
+
|
106
|
+
queue.filter(:odd) do |task|
|
107
|
+
task.tag % 2 == 1
|
108
|
+
end
|
109
|
+
|
110
|
+
assert_equal tasks[1], queue.peek(:odd)
|
111
|
+
assert_equal 5, queue.length(:odd)
|
112
|
+
|
113
|
+
assert_equal [ tasks[1], tasks[3], tasks[5], tasks[7], tasks[9] ], queue.pull(:odd)
|
114
|
+
|
115
|
+
assert_equal 5, queue.length
|
116
|
+
assert_equal 0, queue.length(:odd)
|
117
|
+
|
118
|
+
added_odd = nil
|
119
|
+
|
120
|
+
queue.observe(:odd) do |task|
|
121
|
+
added_odd = task
|
122
|
+
end
|
123
|
+
|
124
|
+
queue << TaggedTask.new(engine, 10)
|
125
|
+
|
126
|
+
assert_equal nil, added_odd
|
127
|
+
|
128
|
+
odd_1 = queue << TaggedTask.new(engine, 11)
|
129
|
+
|
130
|
+
assert_equal odd_1, added_odd
|
131
|
+
|
132
|
+
claimed_task = nil
|
133
|
+
has_run = false
|
134
|
+
|
135
|
+
queue.observe(:odd) do |task|
|
136
|
+
claimed_task = queue.claim(task)
|
137
|
+
has_run = true
|
138
|
+
end
|
139
|
+
|
140
|
+
# Observer callbacks are not triggered on existing data, only on new
|
141
|
+
# insertions.
|
142
|
+
assert_equal false, has_run
|
143
|
+
assert_equal nil, claimed_task
|
144
|
+
assert_equal 7, queue.length
|
145
|
+
assert_equal 1, queue.length(:odd)
|
146
|
+
|
147
|
+
queue << TaggedTask.new(engine, 12)
|
148
|
+
|
149
|
+
assert_equal nil, claimed_task
|
150
|
+
assert_equal 8, queue.length
|
151
|
+
assert_equal 1, queue.length(:odd)
|
152
|
+
|
153
|
+
odd_2 = queue << TaggedTask.new(engine, 13)
|
154
|
+
|
155
|
+
# Adding a task that matches the filter triggers the callback.
|
156
|
+
assert_equal odd_2, claimed_task
|
157
|
+
assert_equal true, has_run
|
158
|
+
|
159
|
+
# Clear out all of the odd entries.
|
160
|
+
queue.pull(:odd)
|
161
|
+
|
162
|
+
claimed_task = nil
|
163
|
+
has_run = false
|
164
|
+
|
165
|
+
queue << TaggedTask.new(engine, 14)
|
166
|
+
|
167
|
+
assert_equal nil, claimed_task
|
168
|
+
assert_equal false, has_run
|
169
|
+
|
170
|
+
odd_2 = queue << TaggedTask.new(engine, 15)
|
171
|
+
|
172
|
+
assert_equal odd_2, claimed_task
|
173
|
+
assert_equal true, has_run
|
174
|
+
|
175
|
+
assert_equal 8, queue.length
|
176
|
+
assert_equal 0, queue.length(:odd)
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_can_add_during_observe
|
180
|
+
queue = Pigeon::Queue.new
|
181
|
+
|
182
|
+
queue.observe do |task|
|
183
|
+
if (task.tag < 10)
|
184
|
+
queue.claim(task)
|
185
|
+
|
186
|
+
queue << TaggedTask.new(engine, task.tag + 1)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
queue << TaggedTask.new(engine, 0)
|
191
|
+
|
192
|
+
assert queue.peek
|
193
|
+
assert_equal 10, queue.peek.tag
|
194
|
+
assert_equal 1, queue.length
|
195
|
+
assert queue.peek
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class PigeonSchedulerTest < Test::Unit::TestCase
|
4
|
+
class TaggedTask < Pigeon::Task
|
5
|
+
attr_accessor :tag
|
6
|
+
|
7
|
+
def initialize(engine, tag)
|
8
|
+
super(engine)
|
9
|
+
@tag = tag
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"<#{@tag}>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def engine
|
18
|
+
@engine ||= Pigeon::Engine.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_defaults
|
22
|
+
scheduler = Pigeon::Scheduler.new
|
23
|
+
|
24
|
+
assert_equal true, scheduler.default_queue.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_queued
|
28
|
+
queue = Pigeon::Queue.new
|
29
|
+
|
30
|
+
scheduler = Pigeon::Scheduler.new(queue)
|
31
|
+
|
32
|
+
count = 1000
|
33
|
+
|
34
|
+
count.times do |n|
|
35
|
+
queue << TaggedTask.new(engine, n)
|
36
|
+
end
|
37
|
+
|
38
|
+
assert_eventually(5) do
|
39
|
+
queue.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
assert_equal 0, scheduler.processors.select(&:task?).length
|
43
|
+
assert_equal 0, queue.length
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_add
|
47
|
+
queue = Pigeon::Queue.new
|
48
|
+
|
49
|
+
scheduler = Pigeon::Scheduler.new(queue)
|
50
|
+
|
51
|
+
count = 1000
|
52
|
+
|
53
|
+
backlog = [ ]
|
54
|
+
count.times do |n|
|
55
|
+
scheduler.add(TaggedTask.new(engine, n * 2 + 1))
|
56
|
+
backlog << TaggedTask.new(engine, n * 2)
|
57
|
+
end
|
58
|
+
|
59
|
+
scheduler.add(backlog)
|
60
|
+
|
61
|
+
assert !queue.empty?
|
62
|
+
|
63
|
+
assert_eventually(5) do
|
64
|
+
queue.empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
assert_equal 0, scheduler.processors.select(&:task?).length
|
68
|
+
assert_equal 0, queue.length
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path(File.join(*%w[ .. helper ]), File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class PigeonSortedArrayTest < Test::Unit::TestCase
|
4
|
+
def test_empty_state
|
5
|
+
array = Pigeon::SortedArray.new
|
6
|
+
|
7
|
+
assert array.empty?
|
8
|
+
assert array.is_a?(Array)
|
9
|
+
assert_equal [ ], array
|
10
|
+
|
11
|
+
dup = array.dup
|
12
|
+
|
13
|
+
assert_equal Pigeon::SortedArray, dup.class
|
14
|
+
|
15
|
+
combined = (array + array)
|
16
|
+
|
17
|
+
assert_equal [ ], combined
|
18
|
+
assert_equal Pigeon::SortedArray, combined.class
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_does_sorting
|
22
|
+
array = Pigeon::SortedArray.new
|
23
|
+
|
24
|
+
test_array = (0..100).to_a.reverse
|
25
|
+
|
26
|
+
array += test_array
|
27
|
+
|
28
|
+
assert_equal (0..100).to_a, array
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_does_sorting_with_insertion_in_order
|
32
|
+
array = Pigeon::SortedArray.new
|
33
|
+
|
34
|
+
10.times do |n|
|
35
|
+
array << n.to_f
|
36
|
+
end
|
37
|
+
|
38
|
+
assert_equal (0..9).to_a.collect(&:to_f), array
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_does_sorting_with_insertion_random_order
|
42
|
+
array = Pigeon::SortedArray.new
|
43
|
+
|
44
|
+
srand
|
45
|
+
(0..10000).to_a.sort_by { rand }.each do |i|
|
46
|
+
array << i
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_equal (0..10000).to_a, array
|
50
|
+
assert_equal 10001, array.length
|
51
|
+
end
|
52
|
+
end
|