mr_darcy 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,11 +21,11 @@ module MrDarcy
21
21
  end
22
22
 
23
23
  def resolve
24
- raise "Can't resolve from #{get_state} state"
24
+ raise RuntimeError, "Can't resolve from #{get_state} state"
25
25
  end
26
26
 
27
27
  def reject
28
- raise "Cant reject from #{get_state} state"
28
+ raise RuntimeError, "Cant reject from #{get_state} state"
29
29
  end
30
30
 
31
31
  private
@@ -1,11 +1,13 @@
1
+ require 'thread'
2
+ require 'fiber'
3
+
1
4
  module MrDarcy
2
5
  module Promise
3
6
  class Thread < Base
4
7
 
5
8
  def initialize *args
6
- @wait_lock = Mutex.new
7
- @wait_cond = ConditionVariable.new
8
- @wait_lock.lock
9
+ @semaphore = Mutex.new
10
+ semaphore.synchronize { @complete = false }
9
11
  super
10
12
  end
11
13
 
@@ -19,43 +21,60 @@ module MrDarcy
19
21
  self
20
22
  end
21
23
 
22
- def resolve value
23
- super
24
- @wait_cond.signal
25
- end
26
-
27
- def reject value
28
- super
29
- @wait_cond.signal
30
- end
31
-
32
24
  private
33
25
 
34
26
  def schedule_promise &block
35
27
  ::Thread.new &block
36
28
  end
37
29
 
38
- def wait_if_unresolved
39
- @wait_cond.wait @wait_lock if unresolved?
30
+ def did_resolve value
31
+ complete!
40
32
  end
41
33
 
42
- def semaphore
43
- @semaphore ||= Mutex.new
34
+ def did_reject value
35
+ complete!
36
+ end
37
+
38
+ def wait_if_unresolved
39
+ return if complete?
40
+ semaphore.synchronize do
41
+ @wait = ConditionVariable.new
42
+ @wait.wait(semaphore)
43
+ end
44
44
  end
45
45
 
46
46
  def generate_child_promise
47
47
  ChildPromise.new driver: :thread
48
48
  end
49
49
 
50
+ def complete?
51
+ semaphore.synchronize { @complete }
52
+ end
53
+
54
+ def complete!
55
+ semaphore.synchronize do
56
+ @complete = true
57
+ @wait.broadcast if @wait
58
+ end
59
+ end
60
+
61
+ def semaphore
62
+ @semaphore
63
+ end
64
+
50
65
  def set_value_to value
51
66
  semaphore.synchronize { super }
52
67
  end
53
68
 
54
- def state_machine_resolve
69
+ def state_machine
70
+ semaphore.synchronize { super }
71
+ end
72
+
73
+ def child_promise
55
74
  semaphore.synchronize { super }
56
75
  end
57
76
 
58
- def state_machine_reject
77
+ def value
59
78
  semaphore.synchronize { super }
60
79
  end
61
80
 
data/lib/mr_darcy/role.rb CHANGED
@@ -11,20 +11,23 @@ module MrDarcy
11
11
  def pollute player
12
12
  guard_against_false_players player
13
13
 
14
- @module.instance_methods.each do |method_name|
15
- implementation = @module.instance_method method_name
16
- player.define_singleton_method method_name, implementation
14
+ if jruby?
15
+ pollute_with_module_extension player
16
+ else
17
+ pollute_with_singleton_methods player
17
18
  end
18
19
  end
19
20
 
20
21
  def clean player
21
- @module.instance_methods.each do |method_name|
22
- player.singleton_class.send :remove_method, method_name if player.respond_to? method_name
23
- end
22
+ clean_singleton_methods player unless jruby?
24
23
  end
25
24
 
26
25
  private
27
26
 
27
+ def jruby?
28
+ RUBY_ENGINE == 'jruby'
29
+ end
30
+
28
31
  def guard_against_false_players player
29
32
  options.each do |test_type, values|
30
33
  case test_type
@@ -41,5 +44,22 @@ module MrDarcy
41
44
  end
42
45
  end
43
46
  end
47
+
48
+ def pollute_with_module_extension player
49
+ player.send :extend, @module
50
+ end
51
+
52
+ def pollute_with_singleton_methods player
53
+ @module.instance_methods.each do |method_name|
54
+ implementation = @module.instance_method method_name
55
+ player.define_singleton_method method_name, implementation
56
+ end
57
+ end
58
+
59
+ def clean_singleton_methods player
60
+ @module.instance_methods.each do |method_name|
61
+ player.singleton_class.send :remove_method, method_name if player.respond_to? method_name
62
+ end
63
+ end
44
64
  end
45
65
  end
@@ -1,3 +1,3 @@
1
1
  module MrDarcy
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -22,7 +22,7 @@ class BankTransfer < MrDarcy::Context
22
22
  money_source.subtract_funds amount
23
23
  money_destination.receive_funds amount
24
24
  else
25
- raise "insufficient funds"
25
+ raise RuntimeError, "insufficient funds"
26
26
  end
27
27
  amount
28
28
  end
@@ -35,28 +35,24 @@ describe 'DCI Bank Transfer' do
35
35
  let(:money_destination) { Account.new destination_balance }
36
36
 
37
37
  MrDarcy.all_drivers.each do |driver|
38
- if driver == :synchronous
39
- describe "Driver #{driver}" do
40
- let(:context) { BankTransfer.new money_source: money_source, money_destination: money_destination, driver: driver }
38
+ describe "Driver #{driver}" do
39
+ let(:context) { BankTransfer.new money_source: money_source, money_destination: money_destination, driver: driver }
41
40
 
42
- When 'the source balance is 10' do
43
- let(:source_balance) { 10 }
41
+ When 'the source balance is 10' do
42
+ let(:source_balance) { 10 }
44
43
 
45
- And 'the destination balance is 5' do
46
- let(:destination_balance) { 5 }
44
+ And 'the destination balance is 5' do
45
+ let(:destination_balance) { 5 }
47
46
 
48
- When 'I transfer 8' do
49
- subject { context.transfer(8).final }
47
+ When 'I transfer 8' do
48
+ subject { context.transfer(8).final }
50
49
 
51
- its('money_source.available_balance') { should eq 2 }
52
- its('money_destination.available_balance') { should eq 13 }
53
- its(:result) { should be_nil }
54
- end
50
+ its('money_source.available_balance') { should eq 2 }
51
+ its('money_destination.available_balance') { should eq 13 }
52
+ its(:result) { should eq 8 }
55
53
  end
56
54
  end
57
55
  end
58
- else
59
- pending "not working with driver #{driver} :("
60
56
  end
61
57
  end
62
58
  end
@@ -1,22 +1,25 @@
1
- require 'spec_helper'
2
- require 'eventmachine'
3
- require 'em-http-request'
1
+ unless RUBY_ENGINE=='jruby'
2
+ require 'spec_helper'
3
+ require 'eventmachine'
4
+ require 'em-http-request'
4
5
 
5
- describe "Wrapping em-http-request" do
6
- let(:promise) do
7
- MrDarcy::Promise.new driver: :em do |p|
8
- http = EM::HttpRequest.new('http://camp.ruby.org.nz/').get
9
- http.errback do
10
- p.reject http.error
11
- end
12
- http.callback do
13
- p.resolve http.response
14
- end
6
+ describe "Wrapping em-http-request" do
7
+ let(:promise) do
8
+ MrDarcy::Promise.new driver: :em do |p|
9
+ http = EM::HttpRequest.new('http://camp.ruby.org.nz/').get
10
+ http.errback do
11
+ p.reject http.error
12
+ end
13
+ http.callback do
14
+ p.resolve http.response
15
+ end
16
+ end.final
15
17
  end
16
- end
17
18
 
18
- subject { promise }
19
+ subject { promise }
20
+
21
+ it_should_behave_like 'a resolved promise'
22
+ its(:result) { should match /Rails Camp NZ/i }
23
+ end
19
24
 
20
- it_should_behave_like 'a resolved promise'
21
- its(:result) { should match /Rails Camp NZ/i }
22
25
  end
@@ -4,8 +4,8 @@ describe "Promise with fail" do
4
4
 
5
5
  MrDarcy.all_drivers.each do |driver|
6
6
  describe "with driver #{driver}" do
7
- let(:promise) { MrDarcy::Promise.new(driver: driver, &promise_block).fail { |v| v+1 } }
8
- subject { promise }
7
+ let(:promise) { MrDarcy::Promise.new(driver: driver, &promise_block) }
8
+ subject { promise.fail { |v| v+1 } }
9
9
 
10
10
  When 'the promise resolves' do
11
11
  let(:promise_block) { proc { |p| p.resolve 1 } }
@@ -73,7 +73,7 @@ describe MrDarcy::Promise::Base do
73
73
  before { mock_promise.reject :bad }
74
74
 
75
75
  When 'the fail block re-fails' do
76
- let(:fail_block) { proc { raise :bad } }
76
+ let(:fail_block) { proc { raise RuntimeError, :bad } }
77
77
 
78
78
  it_behaves_like 'a rejected promise'
79
79
  end
@@ -4,8 +4,6 @@ describe MrDarcy::Promise::ChildPromise do
4
4
  let(:child_promise) { MrDarcy::Promise::ChildPromise.new driver: :Synchronous }
5
5
  subject { child_promise }
6
6
 
7
- it { should be_a MrDarcy::Deferred }
8
-
9
7
  it { should respond_to :resolve_block }
10
8
  it { should respond_to :reject_block }
11
9
 
@@ -26,37 +24,36 @@ describe MrDarcy::Promise::ChildPromise do
26
24
  let(:resolve_block) { proc { :new_value } }
27
25
 
28
26
  it 'resolves' do
29
- expect { subject }.to change { child_promise.resolved? }.from(false).to(true)
27
+ expect { subject }.to change { child_promise.promise.resolved? }.from(false).to(true)
30
28
  end
31
29
 
32
30
  it 'sets the new value' do
33
- expect { subject }.to change { child_promise.result }.to(:new_value)
31
+ expect { subject }.to change { child_promise.promise.result }.to(:new_value)
34
32
  end
35
33
  end
36
34
 
37
35
  When 'the resolve block returns a new promise' do
38
- let(:promise_block) { proc {} }
39
- let(:promise) { MrDarcy::Promise::Synchronous.new promise_block }
36
+ let(:promise) { MrDarcy::Promise::Synchronous.new proc {} }
40
37
  let(:resolve_block) { proc { promise } }
41
38
 
42
39
  it 'doesn\'t resolve' do
43
- expect { subject }.not_to change { child_promise.resolved? }
40
+ expect { subject }.not_to change { child_promise.promise.resolved? }
44
41
  end
45
42
 
46
43
  it 'doesn\'t set the value' do
47
- expect { subject }.not_to change { child_promise.result }
44
+ expect { subject }.not_to change { child_promise.promise.result }
48
45
  end
49
46
 
50
47
  When 'the promise eventually resolves' do
51
- before { child_promise.parent_resolved resolve_value }
48
+ before { child_promise.parent_resolved resolve_value }
52
49
  subject { promise.resolve :mr_good_stuff }
53
50
 
54
51
  it 'resolves' do
55
- expect { subject }.to change{ child_promise.resolved? }.from(false).to(true)
52
+ expect { subject }.to change{ child_promise.promise.resolved? }.from(false).to(true)
56
53
  end
57
54
 
58
55
  it 'has the new value' do
59
- expect { subject }.to change { child_promise.result }.to(:mr_good_stuff)
56
+ expect { subject }.to change { child_promise.promise.result }.to(:mr_good_stuff)
60
57
  end
61
58
  end
62
59
 
@@ -65,11 +62,11 @@ describe MrDarcy::Promise::ChildPromise do
65
62
  subject { promise.reject :mr_bad_stuff }
66
63
 
67
64
  it 'rejects' do
68
- expect { subject }.to change{ child_promise.rejected? }.from(false).to(true)
65
+ expect { subject }.to change{ child_promise.promise.rejected? }.from(false).to(true)
69
66
  end
70
67
 
71
68
  it 'has the new value' do
72
- expect { subject }.to change { child_promise.result }.to(:mr_bad_stuff)
69
+ expect { subject }.to change { child_promise.promise.result }.to(:mr_bad_stuff)
73
70
  end
74
71
  end
75
72
  end
@@ -78,12 +75,12 @@ describe MrDarcy::Promise::ChildPromise do
78
75
  Otherwise do
79
76
  it 'is resolved' do
80
77
  subject
81
- expect(child_promise).to be_resolved
78
+ expect(child_promise.promise).to be_resolved
82
79
  end
83
80
 
84
81
  it 'is resolved with the supplied value' do
85
82
  subject
86
- expect(child_promise.result).to eq(resolve_value)
83
+ expect(child_promise.promise.result).to eq(resolve_value)
87
84
  end
88
85
  end
89
86
  end
@@ -105,25 +102,24 @@ describe MrDarcy::Promise::ChildPromise do
105
102
  let(:reject_block) { proc { :new_value } }
106
103
 
107
104
  it 'resolves' do
108
- expect { subject }.to change { child_promise.resolved? }.from(false).to(true)
105
+ expect { subject }.to change { child_promise.promise.resolved? }.from(false).to(true)
109
106
  end
110
107
 
111
108
  it 'sets the new value' do
112
- expect { subject }.to change { child_promise.result }.to(:new_value)
109
+ expect { subject }.to change { child_promise.promise.result }.to(:new_value)
113
110
  end
114
111
  end
115
112
 
116
113
  When 'the reject block returns a new promise' do
117
- let(:promise_block) { proc {} }
118
- let(:promise) { MrDarcy::Promise::Synchronous.new promise_block }
114
+ let(:promise) { MrDarcy::Promise::Synchronous.new proc {} }
119
115
  let(:reject_block) { proc { promise } }
120
116
 
121
117
  it 'doesn\'t reject' do
122
- expect { subject }.not_to change { child_promise.rejected? }
118
+ expect { subject }.not_to change { child_promise.promise.rejected? }
123
119
  end
124
120
 
125
121
  it 'doesn\'t set the value' do
126
- expect { subject }.not_to change { child_promise.result }
122
+ expect { subject }.not_to change { child_promise.promise.result }
127
123
  end
128
124
 
129
125
  When 'the promise eventually resolves' do
@@ -131,11 +127,11 @@ describe MrDarcy::Promise::ChildPromise do
131
127
  subject { promise.resolve :mr_good_stuff }
132
128
 
133
129
  it 'resolves' do
134
- expect { subject }.to change{ child_promise.resolved? }.from(false).to(true)
130
+ expect { subject }.to change{ child_promise.promise.resolved? }.from(false).to(true)
135
131
  end
136
132
 
137
133
  it 'has the new value' do
138
- expect { subject }.to change { child_promise.result }.to(:mr_good_stuff)
134
+ expect { subject }.to change { child_promise.promise.result }.to(:mr_good_stuff)
139
135
  end
140
136
  end
141
137
 
@@ -144,11 +140,11 @@ describe MrDarcy::Promise::ChildPromise do
144
140
  subject { promise.reject :mr_bad_stuff }
145
141
 
146
142
  it 'rejects' do
147
- expect { subject }.to change{ child_promise.rejected? }.from(false).to(true)
143
+ expect { subject }.to change{ child_promise.promise.rejected? }.from(false).to(true)
148
144
  end
149
145
 
150
146
  it 'has the new value' do
151
- expect { subject }.to change { child_promise.result }.to(:mr_bad_stuff)
147
+ expect { subject }.to change { child_promise.promise.result }.to(:mr_bad_stuff)
152
148
  end
153
149
  end
154
150
  end
@@ -157,12 +153,12 @@ describe MrDarcy::Promise::ChildPromise do
157
153
  Otherwise do
158
154
  it 'is rejected' do
159
155
  subject
160
- expect(child_promise).to be_rejected
156
+ expect(child_promise.promise).to be_rejected
161
157
  end
162
158
 
163
159
  it 'is rejected with the supplied value' do
164
160
  subject
165
- expect(child_promise.result).to eq(reject_value)
161
+ expect(child_promise.promise.result).to eq(reject_value)
166
162
  end
167
163
  end
168
164
  end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Promise::EM do
4
+ describe '#initialize' do
5
+ describe 'JRuby warning' do
6
+ subject { -> { MrDarcy::Promise::EM.new proc {} } }
7
+
8
+ When 'running on jruby' do
9
+ before { stub_const 'RUBY_ENGINE', 'jruby' }
10
+
11
+ it { should raise_error }
12
+ end
13
+
14
+ Otherwise do
15
+ it { should_not raise_error }
16
+ end unless RUBY_ENGINE == 'jruby'
17
+ end
18
+
19
+ end
20
+ end