gexp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +1 -0
  6. data/gexp.gemspec +32 -0
  7. data/lib/gexp.rb +16 -0
  8. data/lib/gexp/command.rb +50 -0
  9. data/lib/gexp/command/object.rb +37 -0
  10. data/lib/gexp/command/stack.rb +50 -0
  11. data/lib/gexp/handler.rb +25 -0
  12. data/lib/gexp/handler/caller.rb +8 -0
  13. data/lib/gexp/handler/check.rb +9 -0
  14. data/lib/gexp/handler/check/item.rb +34 -0
  15. data/lib/gexp/handler/check/resources.rb +56 -0
  16. data/lib/gexp/handler/modify.rb +9 -0
  17. data/lib/gexp/handler/modify/resources.rb +81 -0
  18. data/lib/gexp/handler/producer.rb +61 -0
  19. data/lib/gexp/handler/transition.rb +44 -0
  20. data/lib/gexp/handler/transition/builder.rb +33 -0
  21. data/lib/gexp/mongoid.rb +4 -0
  22. data/lib/gexp/mongoid/transaction.rb +266 -0
  23. data/lib/gexp/object.rb +39 -0
  24. data/lib/gexp/receiver.rb +33 -0
  25. data/lib/gexp/state_definition.rb +4 -0
  26. data/lib/gexp/state_definition/state_machine.rb +90 -0
  27. data/lib/gexp/version.rb +3 -0
  28. data/spec/gexp/command/object_spec.rb +84 -0
  29. data/spec/gexp/command/stack_spec.rb +74 -0
  30. data/spec/gexp/command_spec.rb +59 -0
  31. data/spec/gexp/handler/check/item_spec.rb +45 -0
  32. data/spec/gexp/handler/check/resources_spec.rb +81 -0
  33. data/spec/gexp/handler/check_spec.rb +5 -0
  34. data/spec/gexp/handler/modify/resources_spec.rb +96 -0
  35. data/spec/gexp/handler/modify_spec.rb +6 -0
  36. data/spec/gexp/handler/producer_spec.rb +85 -0
  37. data/spec/gexp/handler/transition/builder_spec.rb +122 -0
  38. data/spec/gexp/handler/transition_spec.rb +14 -0
  39. data/spec/gexp/mongoid/transaction_spec.rb +210 -0
  40. data/spec/gexp/state_definition/state_machine_spec.rb +48 -0
  41. data/spec/spec_helper.rb +10 -0
  42. metadata +210 -0
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb')
3
+
4
+ describe Gexp::Handler::Check do
5
+ end
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper.rb')
3
+
4
+ describe Gexp::Handler::Modify::Resources do
5
+
6
+ before do
7
+ @user = User.new
8
+ @object = Item.new
9
+
10
+ subject.user = @user
11
+ subject.object = @object
12
+ end
13
+
14
+ context "#normilize" do
15
+
16
+ it "с положительным параметром" do
17
+ value = 100500
18
+ subject.normalize(:undefined, value).should == value
19
+ end
20
+
21
+ it "с отрицательным параметром" do
22
+ value = -3
23
+ subject.normalize(:undefined, value).should be_zero
24
+ end
25
+
26
+ end
27
+
28
+ context "#normalize_energy" do
29
+
30
+ before { @max_energy = 20 }
31
+
32
+ it "с отрицательным значением" do
33
+ value = -1
34
+ subject.normalize(:energy, value).should be_zero
35
+ end
36
+
37
+ context "Если не привышаем лимит" do
38
+ before { stub(@user).max_energy.once { @max_energy } }
39
+
40
+ it "с нормальным значением" do
41
+ value = @max_energy / 2
42
+ subject.normalize(:energy, value).should == value
43
+ end
44
+
45
+ it "с максимальным значением" do
46
+ value = @max_energy
47
+ subject.normalize(:energy, value).should == value
48
+ end
49
+
50
+ end
51
+
52
+ it "со сверх большим значением" do
53
+ stub(@user).max_energy.twice { @max_energy }
54
+ value = @max_energy + 1
55
+ subject.normalize(:energy, value).should == @max_energy
56
+ end
57
+
58
+ end
59
+
60
+ context "Изменение ресурсов" do
61
+
62
+ it "Энергия должна быть начисленна" do
63
+ @user.energy = 5
64
+ subject.process({ energy: 5 })
65
+ @user.energy.should == 10
66
+ end
67
+
68
+ it "Энергия должна списываться" do
69
+ @user.energy = 10
70
+ subject.process({ energy: -5 })
71
+ @user.energy.should == 5
72
+ end
73
+
74
+ it "Энергия должна списываться, а экспа начисляться" do
75
+ @user.energy = 10
76
+ @user.exp = 10
77
+ subject.process({ energy: -5, exp: 5 })
78
+ @user.energy.should == 5
79
+ @user.exp.should == 15
80
+ end
81
+
82
+ it "Если ресурса не хватает, полностью прерываем транзакцию" do
83
+ @user.energy = 10
84
+ @user.exp = 10
85
+
86
+ lambda {
87
+ subject.process({ exp: 5, energy: -11 })
88
+ }.should raise_error /out_of_resource\-energy/
89
+
90
+ @user.energy.should == 10
91
+ @user.exp.should == 10
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb')
3
+
4
+ describe Gexp::Handler::Modify do
5
+
6
+ end
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb')
3
+
4
+ describe Gexp::Handler::Producer do
5
+
6
+ let(:objects) do
7
+ {
8
+ object: Object.new,
9
+ provider: Object.new,
10
+ subject: Object.new,
11
+ }
12
+ end
13
+
14
+ let(:emiter) do
15
+ emiter = Gexp::Handler::Producer.new \
16
+ params,
17
+ type,
18
+ objects
19
+ end
20
+
21
+ let(:handler) do
22
+ handler = emiter.emit
23
+ end
24
+
25
+ before do
26
+ emited_class.class.should be_a_kind_of Class
27
+ end
28
+
29
+ context "Caller" do
30
+
31
+ let(:params) do
32
+ [ :object, [ :arg1, :arg2, :arg3 ] ]
33
+ end
34
+
35
+ let(:emited_class) do
36
+ Gexp::Handler::Caller
37
+ end
38
+
39
+ let(:type) do
40
+ end
41
+
42
+ it "build caller for self" do
43
+ handler.should be_a_kind_of emited_class
44
+ end
45
+
46
+ end
47
+
48
+ context "Other Handler" do
49
+
50
+ let(:params) do
51
+ [ :other, :object, { param: :value, other_param: :over_value } ]
52
+ end
53
+
54
+ let(:emited_class) do
55
+ Gexp::Handler.const_get(handler_class).const_set :Other, (Class.new do
56
+ def initialize(*args)
57
+ end
58
+ end)
59
+ end
60
+
61
+ context "Checker" do
62
+
63
+ let(:handler_class) { :Check }
64
+ let(:type) { :chekers }
65
+
66
+ it "build caller for self" do
67
+ handler.should be_a_kind_of emited_class
68
+ end
69
+
70
+ end
71
+
72
+ context "Modifier" do
73
+
74
+ let(:handler_class) { :Modify }
75
+ let(:type) { :modifiers }
76
+
77
+ it "build caller for self" do
78
+ handler.should be_a_kind_of emited_class
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ end
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper.rb')
3
+
4
+ describe Gexp::Handler::Transition::Builder do
5
+
6
+ shared_examples_for Gexp::Handler::Transition::Builder do
7
+
8
+ # let(:to) { to }
9
+
10
+ # let(:from) { from }
11
+
12
+ # let(:event) { event }
13
+
14
+ let(:transition) do
15
+ transition = Object.new
16
+ stub(transition).to_name { to }
17
+ stub(transition).from_name { from }
18
+ stub(transition).event { event }
19
+
20
+ transition
21
+ end
22
+
23
+ # let(:config) do
24
+ # config
25
+ # end
26
+
27
+ # let(:result_chekers) do
28
+ # result_chekers
29
+ # end
30
+
31
+ # let(:result_modifiers) do
32
+ # result_modifiers
33
+ # end
34
+
35
+ let(:object_param) do
36
+ object = Object.new
37
+ stub(object).config { config }
38
+ object
39
+ end
40
+
41
+ let(:subject) do
42
+ Gexp::Handler::Transition::Builder.new \
43
+ transition,
44
+ object_param,
45
+ subject_param,
46
+ provider_param
47
+ end
48
+
49
+ it "should must be given result checkers" do
50
+ subject.checkers.should == result_chekers
51
+ end
52
+
53
+ it "should must be given result modifiers" do
54
+ subject.modifiers.should == result_modifiers
55
+ end
56
+
57
+ end
58
+
59
+ context "Define handler example" do
60
+
61
+ it_behaves_like Gexp::Handler::Transition::Builder do
62
+ let(:to) { :prebuilded }
63
+ let(:from) { :created }
64
+ let(:event) { :place }
65
+ let(:config) do
66
+ {
67
+ events: {
68
+ place: {
69
+ check: [
70
+ [ :resources, :object, { wood: 5, energy: 1 } ],
71
+ [ :object, [ :place_allowed?, :not_blocked? ] ],
72
+ ],
73
+ modify: [
74
+ [ :object, [ :change_tile_type! ] ]
75
+ ]
76
+ },
77
+ sell: {
78
+ check: [
79
+ [ :object, [ :has_current_user? ] ]
80
+ ]
81
+ }
82
+ },
83
+ transitions: {
84
+ created: {
85
+ selled: { },
86
+ prebuilded: {
87
+ check: [
88
+ [ :shared_resources, :object, { 0 => 5 } ]
89
+ ],
90
+ modify: [
91
+ [ :shared_resources, :object, { 0 => 5 } ],
92
+ [ :resources, :object, { wood: -5, energy: -1 } ],
93
+ [ :shared_resources, :object, { 0 => -5 } ]
94
+ ]
95
+ }
96
+ }
97
+ }
98
+ }
99
+ end
100
+
101
+ let(:result_chekers) {
102
+ [
103
+ [ :resources, :object, { wood: 5, energy: 1 } ],
104
+ [ :object, [ :place_allowed?, :not_blocked? ] ],
105
+ [ :shared_resources, :object, { 0 => 5 } ],
106
+ ]
107
+ }
108
+ let(:result_modifiers) {
109
+ [
110
+ [ :object, [ :change_tile_type! ] ],
111
+ [ :shared_resources, :object, { 0 => 5 } ],
112
+ [ :resources, :object, { wood: -5, energy: -1 } ],
113
+ [ :shared_resources, :object, { 0 => -5 } ]
114
+ ]
115
+ }
116
+ let(:subject_param) { Object.new }
117
+ let(:provider_param) { Object.new }
118
+
119
+ end
120
+
121
+ end
122
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb')
3
+
4
+ describe Gexp::Handler::Transition do
5
+
6
+ shared_examples_for "construct handler" do
7
+
8
+ let(:object) { Object.new }
9
+ let(:subject) { Object.new }
10
+ let(:provider) {}
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,210 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper.rb')
3
+
4
+ describe Gexp::Mongoid::Transaction do
5
+
6
+ context "Transactional Object" do
7
+
8
+ before do
9
+
10
+ class Foo < Gexp::Mongoid::Transaction::Base
11
+ field :name, type: String
12
+ field :quantity, type: Integer
13
+ end
14
+
15
+ class Baz < Gexp::Mongoid::Transaction::Base
16
+ field :name, type: String
17
+ field :quantity, type: Integer
18
+ end
19
+
20
+ @foo = Foo.create(name: 'foo', quantity: 0)
21
+
22
+ end
23
+
24
+ it "Проверка полей Foo#*" # TODO: нужены mongoid-rspec матчеры
25
+
26
+ context "Жизненный цикл транзакции" do
27
+
28
+ def inner_assets_for(foo, transaction)
29
+ foo.name = 'new_foo'
30
+ foo.name.should == 'new_foo'
31
+ foo._updated['name'].should == 'new_foo'
32
+ foo.attributes['name'].should == 'foo'
33
+ foo.transaction.should == transaction
34
+ foo._version.should be_zero
35
+
36
+ foo.should be_dirty_uncommited
37
+ foo.save
38
+ end
39
+
40
+ def outer_assets_for(foo)
41
+ foo.reload
42
+ foo.name.should == 'new_foo'
43
+ foo._transaction_id.should be_nil
44
+ foo._updated.should be_nil
45
+ foo._version.should_not be_zero
46
+ foo.should be_clear
47
+ end
48
+
49
+
50
+ it "Изменения без транзакции" do
51
+ @foo.reload
52
+ @foo.name = 'new_foo'
53
+ @foo.name.should == 'new_foo'
54
+ @foo._updated.should be_nil
55
+ @foo.transaction.should be_nil
56
+ @foo.save
57
+ @foo.reload
58
+ @foo.name.should == 'new_foo'
59
+ end
60
+
61
+ it "Транзакция на внутреннем новом объекте" do
62
+ foo = nil
63
+
64
+ Gexp::Mongoid::Transaction.with do |context|
65
+ foo = Foo.create(name: 'foo', quantity: 0)
66
+ inner_assets_for foo, context.transaction
67
+ end
68
+
69
+ outer_assets_for foo
70
+ end
71
+
72
+ it "Транзакция на внутреннем загруженном объекте" do
73
+
74
+ exist = Foo.create(name: 'foo', quantity: 0)
75
+ foo = nil
76
+ Gexp::Mongoid::Transaction.with do |context|
77
+ foo = Foo.find(exist)
78
+ inner_assets_for foo, context.transaction
79
+ end
80
+
81
+ outer_assets_for foo
82
+ end
83
+
84
+ it "Транзакция на внешнем новом объекте" do
85
+ foo = Foo.create(name: 'foo', quantity: 0)
86
+ Gexp::Mongoid::Transaction.with do |context|
87
+ inner_assets_for foo, context.transaction
88
+ end
89
+
90
+ outer_assets_for foo
91
+ end
92
+
93
+ it "Транзакция на внешнем загруженном объекте" do
94
+ exist = Foo.create(name: 'foo', quantity: 0)
95
+ foo = Foo.create(name: 'foo', quantity: 0)
96
+
97
+ Gexp::Mongoid::Transaction.with(foo) do |context|
98
+ foo.transaction.should == context.transaction
99
+ context.transaction.objects.include?(foo).should == true
100
+ inner_assets_for foo, context.transaction
101
+ end
102
+
103
+ outer_assets_for foo
104
+ end
105
+
106
+ end
107
+
108
+ context "Проверка признаков объекта" do
109
+
110
+ it "Чистый объект" do
111
+ @foo.should be_clear
112
+ @foo.should_not be_dirty_commited
113
+ @foo.should_not be_dirty_uncommited
114
+ end
115
+
116
+ it "Грязный закомиченный объект" do
117
+ @foo.create_update
118
+ @foo._transaction_id = '12312312asd3123'
119
+
120
+ @foo.should_not be_clear
121
+ @foo.should be_dirty_commited
122
+ @foo.should_not be_dirty_uncommited
123
+ end
124
+
125
+ it "Грязный незакомиченынй объект" do
126
+ @foo.create_update
127
+ @foo.transaction = Gexp::Mongoid::Transaction::Instance.create
128
+ @foo.should_not be_clear
129
+ @foo.should_not be_dirty_commited
130
+ @foo.should be_dirty_uncommited
131
+
132
+ Gexp::Mongoid::Transaction::Observer.finish_transaction!
133
+ end
134
+
135
+ end
136
+
137
+ context "Загрузка и запись" do
138
+
139
+ before do
140
+ @foo = Foo.create(name: 'name', quantity: 0)
141
+ @baz = Baz.create(name: 'name', quantity: 0)
142
+ end
143
+
144
+ it "чистого объекта" do
145
+ loaded = Foo.find(@foo.id)
146
+ loaded.should be_clear
147
+ end
148
+
149
+ it "В нормальном режиме" do
150
+ Gexp::Mongoid::Transaction.with do |context|
151
+ foo = Foo.find(@foo.id)
152
+ foo.name = 'new_name_foo'
153
+
154
+ baz = Baz.find(@baz.id)
155
+ baz.name = 'new_name_baz'
156
+ end
157
+
158
+ @foo.reload
159
+ @foo.name.should == 'new_name_foo'
160
+ @foo._version.should_not be_zero
161
+ @foo.should be_clear
162
+
163
+ @baz.reload
164
+ @baz.name.should == 'new_name_baz'
165
+ @baz._version.should_not be_zero
166
+ @baz.should be_clear
167
+ end
168
+
169
+ it "грязного не закоммиченного объекта с проваленной транзакцией" do
170
+ obj = @foo
171
+ lambda {
172
+ Gexp::Mongoid::Transaction.with do |context|
173
+ obj.name = 'new_name'
174
+ obj.should be_dirty_uncommited
175
+ obj.save
176
+ obj.reload
177
+ obj.name.should == 'name'
178
+ raise 'Something wrong'
179
+ end
180
+ }.should raise_error /Something wrong/
181
+
182
+ loaded = Foo.find(obj.id)
183
+ loaded.should be_clear
184
+
185
+ loaded.name.should == 'name'
186
+ end
187
+
188
+ it "грязного не закоммиченного объекта при проваленом коммите транзакции" do
189
+ lambda {
190
+ Gexp::Mongoid::Transaction.with do |context|
191
+ stub(context).end_transaction { raise 'Something wrong' }
192
+ @foo.name = 'new_name'
193
+ @foo.save
194
+ end
195
+ }.should raise_error /Something wrong/
196
+
197
+ @foo.should be_dirty
198
+ @foo.should be_dirty_commited
199
+ #mock(@foo).clear_commited!.once
200
+ mock(@foo).clear_uncommited!.never
201
+ @foo.reload
202
+ @foo.name.should == 'new_name'
203
+ @foo.should be_clear
204
+ end
205
+
206
+ end
207
+
208
+ end
209
+
210
+ end