simple-future 1.0.0.pre1 → 1.0.0.pre2

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.
@@ -0,0 +1,180 @@
1
+ require 'spec_helper'
2
+
3
+ def time_it(&blk)
4
+ before = Time.now
5
+ blk.call()
6
+ return Time.now - before
7
+ end
8
+
9
+ class ScratchError < RuntimeError; end
10
+ class BogoError < RuntimeError
11
+ def initialize(e)
12
+ super(e)
13
+ @unmarshalableValue = proc{42}
14
+ end
15
+ end
16
+
17
+ describe "SimpleFuture" do
18
+ it "lets you specify the number of tasks" do
19
+ expect(SimpleFuture.max_tasks).to be > 0
20
+ SimpleFuture.max_tasks = 4
21
+ expect(SimpleFuture.max_tasks).to be 4
22
+ end
23
+
24
+ it "executes a block without changing the current state" do
25
+ foo = 42
26
+ r = SimpleFuture.new do
27
+ foo += 1
28
+ foo
29
+ end
30
+
31
+ expect(r.value).to be 43
32
+ expect(foo).to be 42
33
+ end
34
+
35
+ it "allows non-blocking polling" do
36
+ # We use time-based measurements to test this, so there's the
37
+ # potential for unusual timing conditions to break this test. It
38
+ # shouldn't happen on normal hardware and conditions, though.
39
+ r = SimpleFuture.new do
40
+ sleep 1
41
+ 42
42
+ end
43
+
44
+ expect(r.check_if_ready).to be false
45
+ sleep 2
46
+ expect(r.check_if_ready).to be true
47
+ expect(r.value).to be 42
48
+ end
49
+
50
+ it "correctly returns the block's results" do
51
+ f1 = SimpleFuture.new { sleep 1; 1}
52
+ f2 = SimpleFuture.new { sleep 1; 2}
53
+ f3 = SimpleFuture.new { sleep 1; 3}
54
+ f4 = SimpleFuture.new { sleep 1; 4}
55
+
56
+ expect(f1.value).to be 1
57
+ expect(f2.value).to be 2
58
+ expect(f3.value).to be 3
59
+ expect(f4.value).to be 4
60
+ end
61
+
62
+ it "allows multiple calls to wait" do
63
+ f1 = SimpleFuture.new { 42 }
64
+ f1.wait
65
+ expect(f1.value).to be 42
66
+
67
+ f1.wait
68
+ expect(f1.value).to be 42
69
+
70
+ f1.wait
71
+ expect(f1.value).to be 42
72
+ end
73
+
74
+
75
+
76
+ it "lets you wait until completion and test for that" do
77
+ r = SimpleFuture.new { 12345 }
78
+ expect(r.complete?).to be false
79
+
80
+ r.wait
81
+ expect(r.complete?).to be true
82
+
83
+ expect(r.value).to be 12345
84
+ end
85
+
86
+ it "gracefully handles exceptions thrown by the child" do
87
+ r = SimpleFuture.new { raise ScratchError.new("Foo!") }
88
+ expect {r.wait}.to raise_error(SimpleFuture::ChildError, /Foo!/)
89
+ end
90
+
91
+ it "returns Exception objects if requested" do
92
+ r = SimpleFuture.new { ScratchError.new("not thrown!") }
93
+ r.wait
94
+ expect(r.value.class).to be ScratchError
95
+ expect(r.value.message).to eq "not thrown!"
96
+ end
97
+
98
+ it "attaches the original exception to the ChildError" do
99
+ r = SimpleFuture.new { raise ScratchError.new("Foo!") }
100
+ begin
101
+ r.wait
102
+ rescue SimpleFuture::ChildError => e
103
+ expect(e.cause.class).to be ScratchError
104
+ expect(e.cause.message).to match("Foo!")
105
+ end
106
+ end
107
+
108
+
109
+ it "cleans up completed child processes" do
110
+ first = SimpleFuture.new { sleep 1; 1}
111
+ second = SimpleFuture.new { sleep 2; 2}
112
+ sleep 1.1
113
+
114
+ expect(SimpleFuture.all_done?).to be false
115
+
116
+ # First should now have completed:
117
+ expect(first.complete?).to be true
118
+ expect(second.complete?).to be false
119
+ expect(second.check_if_ready).to be false
120
+
121
+ # Wait for second one to complete, then scrub
122
+ sleep 1
123
+ expect(second.complete?).to be false
124
+ expect(SimpleFuture.all_done?).to be true
125
+ expect(second.complete?).to be true
126
+ end
127
+
128
+ it "does not block when free tasks are available" do
129
+ SimpleFuture.max_tasks = 4
130
+
131
+ tt = time_it {
132
+ sfs = (0..3).map{|i| SimpleFuture.new {sleep 1; i} }
133
+ sfs.each{|sf| sf.value}
134
+ }
135
+ expect(tt).to be < 1.1
136
+ end
137
+
138
+ it "interprets maximum tasks of 0 as meaning no limit on children" do
139
+ SimpleFuture.max_tasks = 0
140
+
141
+ tt = time_it {
142
+ sfs = (0..30).map{|i| SimpleFuture.new {sleep 1; i} }
143
+ sfs.each{|sf| sf.value}
144
+ }
145
+ expect(tt).to be < 1.1
146
+ end
147
+
148
+ it "blocks when the maximum number of children is reached" do
149
+ SimpleFuture.max_tasks = 4
150
+
151
+ tt = time_it {
152
+ sfs = (0..7).map{|i| SimpleFuture.new {sleep 1; i} }
153
+ sfs.each{|sf| sf.value}
154
+ }
155
+ expect(tt).to be > 1
156
+ expect(tt).to be < 2.1
157
+ end
158
+
159
+ it "can block until all active children have finished" do
160
+ SimpleFuture.max_tasks = 4
161
+ sfs = (0..3).map{|i| SimpleFuture.new {sleep 1; i} }
162
+
163
+ SimpleFuture.wait_for_all
164
+
165
+ sfs.each{|sf|
166
+ expect(sf.check_if_ready).to be true
167
+ }
168
+ end
169
+
170
+ it "handles the case where the result isn't marshallable" do
171
+ r = SimpleFuture.new { proc{42} }
172
+ expect {r.value}.to raise_error(SimpleFuture::ResultTypeError, /Proc/)
173
+ end
174
+
175
+ it "handles the case where the exception contains an unmarshallable item" do
176
+ r = SimpleFuture.new { raise BogoError.new("error!") }
177
+ expect {r.value}.to raise_error(SimpleFuture::ResultTypeError, /dumped/)
178
+ end
179
+
180
+ end
@@ -0,0 +1,6 @@
1
+ $: << 'lib'
2
+ require_relative '../lib/simple-future.rb'
3
+
4
+
5
+
6
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-future
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre1
4
+ version: 1.0.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Reuter
@@ -63,7 +63,31 @@ executables: []
63
63
  extensions: []
64
64
  extra_rdoc_files: []
65
65
  files:
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - doc/SimpleFuture.html
70
+ - doc/SimpleFuture/ChildError.html
71
+ - doc/SimpleFuture/Error.html
72
+ - doc/SimpleFuture/ResultTypeError.html
73
+ - doc/_index.html
74
+ - doc/class_list.html
75
+ - doc/css/common.css
76
+ - doc/css/full_list.css
77
+ - doc/css/style.css
78
+ - doc/file.README.html
79
+ - doc/file_list.html
80
+ - doc/frames.html
81
+ - doc/index.html
82
+ - doc/js/app.js
83
+ - doc/js/full_list.js
84
+ - doc/js/jquery.js
85
+ - doc/method_list.html
86
+ - doc/top-level-namespace.html
66
87
  - lib/simple-future.rb
88
+ - simple-future.gemspec
89
+ - spec/simple-future_spec.rb
90
+ - spec/spec_helper.rb
67
91
  homepage: https://github.com/suetanvil/simple-future
68
92
  licenses:
69
93
  - MIT