mr_darcy 0.1.0 → 0.2.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.
@@ -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