-
Notifications
You must be signed in to change notification settings - Fork 13
/
future_spec.rb
113 lines (88 loc) · 2.84 KB
/
future_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
require 'spec_helper'
require 'futuroscope/future'
require 'timeout'
module Futuroscope
describe Future do
it "will return an instant value" do
future = Future.new{ :edballs }
sleep(0.1)
expect(future).to eq(:edballs)
end
it "will execute the future in the background and wait for it" do
future = Future.new{ sleep(1); :edballs }
sleep(1)
Timeout::timeout(0.9) do
expect(future).to eq(:edballs)
end
end
it "delegates some Object methods to the original object's" do
object = [1, 2, 3]
future = Future.new{object}
expect(future.class).to eq(Array)
expect(future).to be_kind_of(Enumerable)
expect(future).to be_a(Enumerable)
expect(future.to_s).to eq(object.to_s)
expect(Future.new { nil }).to be_nil
end
it "delegates missing methods" do
object = [1, 2, 3]
future = Future.new{object}
expect(future).to_not be_empty
end
it "captures exceptions and re-raises them when calling the value" do
future = Future.new{ raise "Ed Balls" }
expect(lambda{
future.inspect
}).to raise_error(Exception)
end
it "returns the original object when future_value gets called" do
object = double
future = Future.new{ object }
expect(future.future_value.object_id === object.object_id).to eq(true)
end
it "marshals a future object by serializing the result value" do
object = [1, 2, 3]
future = Future.new{object}
dumped = Marshal.dump(future)
expect(Marshal.load(dumped).future_value).to eq(object)
end
it "re-raises captured exception when trying to marshal" do
future = Future.new{ raise Exception }
expect(lambda{
Marshal.dump(future)
}).to raise_error(Exception)
end
it "correctly duplicates a future object" do
object = [1, 2, 3]
future = Future.new { object }
expect(future.dup).to eq future
end
it "clones correctly before being resolved" do
object = [1, 2, 3]
future = Future.new { sleep 1; object }
clone = future.clone
expect(clone).to eq object
end
context "when at least another thread is alive" do
# If no threads are alive, the VM raises an exception, therefore we need to ensure there is one.
before :each do
@live_thread = Thread.new { loop { } }
end
it "doesn't hang when 2 threads try to obtain its result before it's finished" do
test_thread = Thread.new do
future = Future.new { sleep 1; 1 }
f1 = Future.new { future + 1 }
f2 = Future.new { future + 2 }
f1.future_value
f2.future_value
end
sleep 2
expect(test_thread).to_not be_alive
test_thread.kill
end
after :each do
@live_thread.kill
end
end
end
end