functional-ruby 0.5.0 → 0.6.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.
- checksums.yaml +4 -4
- data/README.md +154 -562
- data/lib/functional/agent.rb +130 -0
- data/lib/functional/all.rb +9 -1
- data/lib/functional/behavior.rb +72 -39
- data/lib/functional/cached_thread_pool.rb +122 -0
- data/lib/functional/concurrency.rb +32 -24
- data/lib/functional/core.rb +2 -62
- data/lib/functional/event.rb +53 -0
- data/lib/functional/event_machine_defer_proxy.rb +23 -0
- data/lib/functional/fixed_thread_pool.rb +89 -0
- data/lib/functional/future.rb +42 -0
- data/lib/functional/global_thread_pool.rb +3 -0
- data/lib/functional/obligation.rb +121 -0
- data/lib/functional/promise.rb +194 -0
- data/lib/functional/thread_pool.rb +61 -0
- data/lib/functional/utilities.rb +114 -0
- data/lib/functional/version.rb +1 -1
- data/lib/functional.rb +1 -0
- data/lib/functional_ruby.rb +1 -0
- data/md/behavior.md +147 -0
- data/md/concurrency.md +465 -0
- data/md/future.md +32 -0
- data/md/obligation.md +32 -0
- data/md/pattern_matching.md +512 -0
- data/md/promise.md +220 -0
- data/md/utilities.md +53 -0
- data/spec/functional/agent_spec.rb +405 -0
- data/spec/functional/behavior_spec.rb +12 -33
- data/spec/functional/cached_thread_pool_spec.rb +112 -0
- data/spec/functional/concurrency_spec.rb +55 -0
- data/spec/functional/event_machine_defer_proxy_spec.rb +246 -0
- data/spec/functional/event_spec.rb +114 -0
- data/spec/functional/fixed_thread_pool_spec.rb +84 -0
- data/spec/functional/future_spec.rb +115 -0
- data/spec/functional/obligation_shared.rb +121 -0
- data/spec/functional/pattern_matching_spec.rb +10 -8
- data/spec/functional/promise_spec.rb +310 -0
- data/spec/functional/thread_pool_shared.rb +209 -0
- data/spec/functional/utilities_spec.rb +149 -0
- data/spec/spec_helper.rb +2 -0
- metadata +55 -5
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Functional
|
4
|
+
|
5
|
+
share_examples_for 'Thread Pool' do
|
6
|
+
|
7
|
+
context '#running?' do
|
8
|
+
|
9
|
+
it 'returns true when the thread pool is running' do
|
10
|
+
subject.should be_running
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns false when the thread pool is shutting down' do
|
14
|
+
subject.post{ sleep(1) }
|
15
|
+
subject.shutdown
|
16
|
+
subject.should_not be_running
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns false when the thread pool is shutdown' do
|
20
|
+
subject.shutdown
|
21
|
+
subject.should_not be_running
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'returns false when the thread pool is killed' do
|
25
|
+
subject.shutdown
|
26
|
+
subject.should_not be_running
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context '#shutdown?' do
|
31
|
+
|
32
|
+
it 'returns true if #shutdown has been called' do
|
33
|
+
subject.shutdown
|
34
|
+
subject.should be_shutdown
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns false when running' do
|
38
|
+
subject.should_not be_shutdown
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context '#killed?' do
|
43
|
+
|
44
|
+
it 'returns true if tasks were killed at shutdown' do
|
45
|
+
subject.post{ sleep(1) }
|
46
|
+
subject.kill
|
47
|
+
subject.should be_killed
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns false when running' do
|
51
|
+
subject.should_not be_killed
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context '#shutdown' do
|
56
|
+
|
57
|
+
it 'stops accepting new tasks' do
|
58
|
+
subject.post{ sleep(1) }
|
59
|
+
subject.shutdown
|
60
|
+
@expected = false
|
61
|
+
subject.post{ @expected = true }.should be_false
|
62
|
+
sleep(1)
|
63
|
+
@expected.should be_false
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'allows in-progress tasks to complete' do
|
67
|
+
@expected = false
|
68
|
+
subject.post{ sleep(0.5); @expected = true }
|
69
|
+
subject.shutdown
|
70
|
+
sleep(1)
|
71
|
+
@expected.should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'allows pending tasks to complete' do
|
75
|
+
@expected = false
|
76
|
+
subject.post{ sleep(0.2) }
|
77
|
+
subject.post{ sleep(0.2); @expected = true }
|
78
|
+
subject.shutdown
|
79
|
+
sleep(1)
|
80
|
+
@expected.should be_true
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'allows threads to exit normally' do
|
84
|
+
pool = FixedThreadPool.new(5)
|
85
|
+
pool.shutdown
|
86
|
+
sleep(1)
|
87
|
+
pool.status.should be_empty
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context '#kill' do
|
92
|
+
|
93
|
+
it 'stops accepting new tasks' do
|
94
|
+
subject.post{ sleep(1) }
|
95
|
+
subject.kill
|
96
|
+
@expected = false
|
97
|
+
subject.post{ @expected = true }.should be_false
|
98
|
+
sleep(1)
|
99
|
+
@expected.should be_false
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'attempts to kill all in-progress tasks' do
|
103
|
+
@expected = false
|
104
|
+
subject.post{ sleep(1); @expected = true }
|
105
|
+
subject.kill
|
106
|
+
sleep(1)
|
107
|
+
@expected.should be_false
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'rejects all pending tasks' do
|
111
|
+
@expected = false
|
112
|
+
subject.post{ sleep(0.5) }
|
113
|
+
subject.post{ sleep(0.5); @expected = true }
|
114
|
+
subject.kill
|
115
|
+
sleep(1)
|
116
|
+
@expected.should be_false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context '#wait_for_termination' do
|
121
|
+
|
122
|
+
it 'immediately returns true after shutdown has complete' do
|
123
|
+
subject.shutdown
|
124
|
+
subject.wait_for_termination.should be_true
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'blocks indefinitely when timeout it nil' do
|
128
|
+
subject.post{ sleep(1) }
|
129
|
+
subject.shutdown
|
130
|
+
subject.wait_for_termination(nil).should be_true
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'returns true when shutdown sucessfully completes before timeout' do
|
134
|
+
subject.post{ sleep(0.5) }
|
135
|
+
subject.shutdown
|
136
|
+
subject.wait_for_termination(1).should be_true
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'returns false when shutdown fails to complete before timeout' do
|
140
|
+
subject.post{ sleep(1) }
|
141
|
+
subject.shutdown
|
142
|
+
subject.wait_for_termination(0.5).should be_true
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context '#post' do
|
147
|
+
|
148
|
+
it 'raises an exception if no block is given' do
|
149
|
+
lambda {
|
150
|
+
subject.post
|
151
|
+
}.should raise_error(ArgumentError)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'returns true when the block is added to the queue' do
|
155
|
+
subject.post{ nil }.should be_true
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'calls the block with the given arguments' do
|
159
|
+
@expected = nil
|
160
|
+
subject.post(1, 2, 3)do |a, b, c|
|
161
|
+
@expected = a + b + c
|
162
|
+
end
|
163
|
+
sleep(0.1)
|
164
|
+
@expected.should eq 6
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'rejects the block while shutting down' do
|
168
|
+
pool = FixedThreadPool.new(5)
|
169
|
+
pool.post{ sleep(1) }
|
170
|
+
pool.shutdown
|
171
|
+
@expected = nil
|
172
|
+
pool.post(1, 2, 3)do |a, b, c|
|
173
|
+
@expected = a + b + c
|
174
|
+
end
|
175
|
+
@expected.should be_nil
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'returns false while shutting down' do
|
179
|
+
subject.post{ sleep(1) }
|
180
|
+
subject.shutdown
|
181
|
+
subject.post{ nil }.should be_false
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'rejects the block once shutdown' do
|
185
|
+
pool = FixedThreadPool.new(5)
|
186
|
+
pool.shutdown
|
187
|
+
@expected = nil
|
188
|
+
pool.post(1, 2, 3)do |a, b, c|
|
189
|
+
@expected = a + b + c
|
190
|
+
end
|
191
|
+
@expected.should be_nil
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'returns false once shutdown' do
|
195
|
+
subject.post{ nil }
|
196
|
+
subject.shutdown
|
197
|
+
sleep(0.1)
|
198
|
+
subject.post{ nil }.should be_false
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'aliases #<<' do
|
202
|
+
@expected = false
|
203
|
+
subject << proc { @expected = true }
|
204
|
+
sleep(0.1)
|
205
|
+
@expected.should be_true
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fakefs/safe'
|
3
|
+
|
4
|
+
describe 'utilities' do
|
5
|
+
|
6
|
+
context '#repl?' do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@dollar_zero = $0
|
10
|
+
end
|
11
|
+
|
12
|
+
after(:each) do
|
13
|
+
$0 = @dollar_zero
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_dollar_zero(val)
|
17
|
+
$0 = val
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'recognizes IRB' do
|
21
|
+
set_dollar_zero('irb')
|
22
|
+
repl?.should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'recognizes Pry' do
|
26
|
+
set_dollar_zero('pry')
|
27
|
+
repl?.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'recognizes Rails Console' do
|
31
|
+
set_dollar_zero('script/rails')
|
32
|
+
repl?.should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'recognizes Bundle Console' do
|
36
|
+
set_dollar_zero('bin/bundle')
|
37
|
+
repl?.should be_true
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns false when not in a REPL' do
|
41
|
+
set_dollar_zero(__FILE__)
|
42
|
+
repl?.should be_false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context '#safe' do
|
47
|
+
|
48
|
+
it 'allows safe operations' do
|
49
|
+
lambda {
|
50
|
+
safe{ 1 + 1 }
|
51
|
+
}.should_not raise_error(SecurityError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'returns the value of the block when safe' do
|
55
|
+
safe{ 1 + 1 }.should eq 2
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'passes all arguments to the block' do
|
59
|
+
safe(1, 2, 3){|x, y, z| x + y + z }.should eq 6
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'rejects unsafe operations on tainted objects' do
|
63
|
+
lambda {
|
64
|
+
safe{ Signal.trap('INT'.taint) }
|
65
|
+
}.should raise_error(SecurityError)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'rejects the use of #eval' do
|
69
|
+
lambda {
|
70
|
+
safe{ eval 'puts 1' }
|
71
|
+
}.should raise_error(SecurityError)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context '#slurp' do
|
76
|
+
|
77
|
+
before(:all) { FakeFS.activate! }
|
78
|
+
after(:all) { FakeFS.deactivate! }
|
79
|
+
|
80
|
+
let!(:path){ 'slurp.txt' }
|
81
|
+
let!(:text){ 'Hello, world!' }
|
82
|
+
|
83
|
+
it 'returns the contents of the file' do
|
84
|
+
File.open(path, 'w+') {|f| f.write(text) }
|
85
|
+
slurp(path).should eq text
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'raises an exception when the file does not exist' do
|
89
|
+
lambda {
|
90
|
+
slurp('path/does/not/exist')
|
91
|
+
}.should raise_error(Errno::ENOENT)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context '#slurpee' do
|
96
|
+
|
97
|
+
before(:all) { FakeFS.activate! }
|
98
|
+
after(:all) { FakeFS.deactivate! }
|
99
|
+
|
100
|
+
let!(:path){ 'slurp.txt' }
|
101
|
+
let!(:text){ 'You are number 6.' }
|
102
|
+
let!(:erb) { 'You are number <%= 2 * 3 %>.' }
|
103
|
+
|
104
|
+
it 'returns the processed contents of the file' do
|
105
|
+
File.open(path, 'w+') {|f| f.write(erb) }
|
106
|
+
slurpee(path).should eq text
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'raises an exception when the file does not exist' do
|
110
|
+
lambda {
|
111
|
+
slurpee('path/does/not/exist')
|
112
|
+
}.should raise_error(Errno::ENOENT)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context '#delta' do
|
117
|
+
|
118
|
+
it 'computes the delta of two positive values' do
|
119
|
+
delta(10.5, 5.0).should be_within(0.01).of(5.5)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'computes the delta of two negative values' do
|
123
|
+
delta(-10.5, -5.0).should be_within(0.01).of(5.5)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'computes the delta of a positive and negative value' do
|
127
|
+
delta(10.5, -5.0).should be_within(0.01).of(15.5)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'computes the delta of two positive values with a block' do
|
131
|
+
v1 = {:count => 10.5}
|
132
|
+
v2 = {:count => 5.0}
|
133
|
+
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(5.5)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'computes the delta of two negative values with a block' do
|
137
|
+
v1 = {:count => -10.5}
|
138
|
+
v2 = {:count => -5.0}
|
139
|
+
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(5.5)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'computes the delta of a positive and negative value with a block' do
|
143
|
+
v1 = {:count => 10.5}
|
144
|
+
v2 = {:count => -5.0}
|
145
|
+
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(15.5)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: functional-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jerry D'Antonio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
description: |2
|
28
|
-
A gem for adding Erlang and
|
28
|
+
A gem for adding Erlang, Clojure, and Go inspired concurrency and functional programming tools to Ruby.
|
29
29
|
email: jerry.dantonio@gmail.com
|
30
30
|
executables: []
|
31
31
|
extensions: []
|
@@ -35,22 +35,62 @@ extra_rdoc_files:
|
|
35
35
|
files:
|
36
36
|
- README.md
|
37
37
|
- LICENSE
|
38
|
+
- lib/functional/agent.rb
|
38
39
|
- lib/functional/all.rb
|
39
40
|
- lib/functional/behavior.rb
|
40
41
|
- lib/functional/behaviour.rb
|
42
|
+
- lib/functional/cached_thread_pool.rb
|
41
43
|
- lib/functional/concurrency.rb
|
42
44
|
- lib/functional/core.rb
|
45
|
+
- lib/functional/event.rb
|
46
|
+
- lib/functional/event_machine_defer_proxy.rb
|
47
|
+
- lib/functional/fixed_thread_pool.rb
|
48
|
+
- lib/functional/future.rb
|
49
|
+
- lib/functional/global_thread_pool.rb
|
50
|
+
- lib/functional/obligation.rb
|
43
51
|
- lib/functional/pattern_matching.rb
|
52
|
+
- lib/functional/promise.rb
|
53
|
+
- lib/functional/thread_pool.rb
|
54
|
+
- lib/functional/utilities.rb
|
44
55
|
- lib/functional/version.rb
|
56
|
+
- lib/functional.rb
|
57
|
+
- lib/functional_ruby.rb
|
58
|
+
- md/behavior.md
|
59
|
+
- md/concurrency.md
|
60
|
+
- md/future.md
|
61
|
+
- md/obligation.md
|
62
|
+
- md/pattern_matching.md
|
63
|
+
- md/promise.md
|
64
|
+
- md/utilities.md
|
65
|
+
- spec/functional/agent_spec.rb
|
45
66
|
- spec/functional/behavior_spec.rb
|
67
|
+
- spec/functional/cached_thread_pool_spec.rb
|
68
|
+
- spec/functional/concurrency_spec.rb
|
69
|
+
- spec/functional/event_machine_defer_proxy_spec.rb
|
70
|
+
- spec/functional/event_spec.rb
|
71
|
+
- spec/functional/fixed_thread_pool_spec.rb
|
72
|
+
- spec/functional/future_spec.rb
|
46
73
|
- spec/functional/integration_spec.rb
|
74
|
+
- spec/functional/obligation_shared.rb
|
47
75
|
- spec/functional/pattern_matching_spec.rb
|
76
|
+
- spec/functional/promise_spec.rb
|
77
|
+
- spec/functional/thread_pool_shared.rb
|
78
|
+
- spec/functional/utilities_spec.rb
|
48
79
|
- spec/spec_helper.rb
|
49
80
|
homepage: https://github.com/jdantonio/functional-ruby/
|
50
81
|
licenses:
|
51
82
|
- MIT
|
52
83
|
metadata: {}
|
53
|
-
post_install_message:
|
84
|
+
post_install_message: |2
|
85
|
+
hello() -> io:format("Hello, World!").
|
86
|
+
|
87
|
+
package main
|
88
|
+
import "fmt"
|
89
|
+
func main() {
|
90
|
+
fmt.Printf("hello, world")
|
91
|
+
}
|
92
|
+
|
93
|
+
(def hello (fn [] "Hello world"))
|
54
94
|
rdoc_options: []
|
55
95
|
require_paths:
|
56
96
|
- lib
|
@@ -71,8 +111,18 @@ signing_key:
|
|
71
111
|
specification_version: 4
|
72
112
|
summary: Erlang and Clojure inspired functional programming tools for Ruby.
|
73
113
|
test_files:
|
114
|
+
- spec/functional/agent_spec.rb
|
74
115
|
- spec/functional/behavior_spec.rb
|
116
|
+
- spec/functional/cached_thread_pool_spec.rb
|
117
|
+
- spec/functional/concurrency_spec.rb
|
118
|
+
- spec/functional/event_machine_defer_proxy_spec.rb
|
119
|
+
- spec/functional/event_spec.rb
|
120
|
+
- spec/functional/fixed_thread_pool_spec.rb
|
121
|
+
- spec/functional/future_spec.rb
|
75
122
|
- spec/functional/integration_spec.rb
|
123
|
+
- spec/functional/obligation_shared.rb
|
76
124
|
- spec/functional/pattern_matching_spec.rb
|
125
|
+
- spec/functional/promise_spec.rb
|
126
|
+
- spec/functional/thread_pool_shared.rb
|
127
|
+
- spec/functional/utilities_spec.rb
|
77
128
|
- spec/spec_helper.rb
|
78
|
-
has_rdoc:
|