golem_statemachine 0.9

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,95 @@
1
+ require 'test_helper'
2
+ require 'ruby-debug'
3
+
4
+ # Tests specifically designed to address bugs/problems discovered along the way.
5
+ class ProblematicTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @klass = Class.new
9
+ @klass.instance_eval do
10
+ include Golem
11
+ end
12
+ end
13
+
14
+ def test_fire_event_for_multiple_statemachines
15
+
16
+ @klass.instance_eval do
17
+ define_statemachine(:engine) do
18
+ initial_state :stopped
19
+ state :stopped do
20
+ on :start, :to => :idle
21
+ end
22
+ state :idle do
23
+ on :start, :to => :running
24
+ end
25
+ end
26
+ define_statemachine(:fan) do
27
+ initial_state :stopped
28
+ state :stopped do
29
+ on :start, :to => :spinning
30
+ end
31
+ end
32
+ end
33
+
34
+ widget = @klass.new
35
+
36
+ assert_equal :stopped, widget.engine_state
37
+ assert_equal :stopped, widget.fan_state
38
+
39
+ widget.start
40
+
41
+ assert_equal :idle, widget.engine_state
42
+ assert_equal :spinning, widget.fan_state
43
+
44
+ assert_nothing_raised do
45
+ # :fan will raise Golem::ImpossibleEvent, but :engine can proceed, so nothing is raised
46
+ widget.start!
47
+ end
48
+
49
+ assert_equal :running, widget.engine_state
50
+ assert_equal :spinning, widget.fan_state
51
+
52
+ assert !widget.start
53
+
54
+ assert_raise(Golem::ImpossibleEvent) do
55
+ # neither :fan nor :engine can proceed
56
+ widget.start!
57
+ end
58
+
59
+ assert !widget.start
60
+ end
61
+
62
+ def test_fire_entry_action_on_initial_state
63
+ @klass.instance_eval do
64
+ class_eval do
65
+ attr_accessor :off
66
+ end
67
+
68
+ define_statemachine(:engine) do
69
+ initial_state :stopped
70
+ state :stopped do
71
+ enter do |engine|
72
+ engine.off = true
73
+ end
74
+ on :start, :to => :idle
75
+ end
76
+ state :idle do
77
+ enter do |engine|
78
+ engine.off = false
79
+ end
80
+ on :start, :to => :running
81
+ end
82
+ end
83
+ end
84
+
85
+ widget = @klass.new
86
+
87
+ assert_equal :stopped, widget.engine_state
88
+ assert_equal true, widget.off
89
+
90
+ widget.start!
91
+
92
+ assert_equal false, widget.off
93
+ end
94
+ end
95
+
@@ -0,0 +1,106 @@
1
+ require 'test_helper'
2
+ require File.dirname(__FILE__)+'/../examples/seminar'
3
+
4
+ # Test the seminar.rb example.
5
+ class SeminarTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @seminar = Seminar.new
9
+ Seminar.output = File.open("#{self.class.name}_#{self.method_name}.log", 'w')
10
+ end
11
+
12
+ def test_initial_status
13
+ assert_equal :proposed, @seminar.statemachine.initial_state
14
+ end
15
+
16
+ def test_open_for_enrollment
17
+ @seminar.max_class_size = 3
18
+
19
+ @seminar.schedule
20
+ @seminar.open
21
+
22
+ assert_equal :open_for_enrollment, @seminar.status
23
+
24
+ @seminar.enroll_student("socrates")
25
+ @seminar.enroll_student("plato")
26
+
27
+ assert_equal :open_for_enrollment, @seminar.status
28
+
29
+ @seminar.drop_student("socrates")
30
+
31
+ assert_equal :open_for_enrollment, @seminar.status
32
+ assert_equal ["plato"], @seminar.students
33
+
34
+ @seminar.enroll_student("aristotle")
35
+ @seminar.enroll_student("socrates")
36
+
37
+ assert_equal :full, @seminar.status
38
+
39
+ @seminar.drop_student("plato")
40
+
41
+ assert_equal :open_for_enrollment, @seminar.status
42
+ assert_equal ["aristotle", "socrates"], @seminar.students
43
+
44
+ @seminar.enroll_student("zeno")
45
+
46
+ assert_equal :full, @seminar.status
47
+
48
+ @seminar.cancel
49
+
50
+ assert_equal :cancelled, @seminar.status
51
+ @seminar.students.each do |student|
52
+ assert @seminar.notifications_sent.include?("#{student}: the seminar has been cancelled")
53
+ end
54
+ end
55
+
56
+ def test_full
57
+ @seminar.max_class_size = 3
58
+
59
+ @seminar.schedule
60
+ @seminar.open
61
+
62
+ @seminar.enroll_student("socrates")
63
+ @seminar.enroll_student("plato")
64
+ @seminar.enroll_student("aristotle")
65
+
66
+ assert_equal :full, @seminar.status
67
+
68
+ @seminar.enroll_student("zeno")
69
+
70
+ assert_equal :full, @seminar.status
71
+ assert_equal ["socrates", "plato", "aristotle"], @seminar.students
72
+ assert_equal ["zeno"], @seminar.waiting_list
73
+
74
+ @seminar.enroll_student("sofia")
75
+
76
+ assert_equal :full, @seminar.status
77
+ assert_equal ["socrates", "plato", "aristotle"], @seminar.students
78
+ assert_equal ["zeno", "sofia"], @seminar.waiting_list
79
+
80
+ @seminar.drop_student("socrates")
81
+
82
+ assert_equal :full, @seminar.status
83
+ assert_equal ["plato", "aristotle", "zeno"], @seminar.students
84
+ assert_equal ["sofia"], @seminar.waiting_list
85
+
86
+ @seminar.drop_student("aristotle")
87
+
88
+ assert_equal :full, @seminar.status
89
+ assert_equal ["plato", "zeno", "sofia"], @seminar.students
90
+ assert_equal [], @seminar.waiting_list
91
+
92
+ @seminar.enroll_student("dennett")
93
+
94
+ assert_equal :full, @seminar.status
95
+ assert_equal ["plato", "zeno", "sofia"], @seminar.students
96
+ assert_equal ["dennett"], @seminar.waiting_list
97
+
98
+ @seminar.cancel
99
+
100
+ assert_equal :cancelled, @seminar.status
101
+ (@seminar.students + @seminar.waiting_list).each do |student|
102
+ assert @seminar.notifications_sent.include?("#{student}: the seminar has been cancelled")
103
+ end
104
+ end
105
+ end
106
+
@@ -0,0 +1,79 @@
1
+ module StatemachineAssertions
2
+ def assert_equal_arrays(arr1, arr2)
3
+ assert_equal [], arr1 - arr2, "array #{arr1} is not equal to array #{arr2}"
4
+ end
5
+
6
+ def assert_transition_on_event(statemachine, event, from_state, to_state)
7
+ from_state = statemachine.states[from_state]
8
+ to_state = statemachine.states[to_state]
9
+ event = statemachine.events[event]
10
+
11
+ assert_not_nil from_state
12
+ assert_not_nil to_state
13
+ assert_not_nil event
14
+
15
+ failure_msg = "#{statemachine} does not have a transition from #{from_state.name.inspect} to #{to_state.name.inspect} on event #{event.name.inspect}"
16
+ failure_msg << "\n\tHas: #{from_state.transitions_on_event[event].collect{|tr| tr.to_s}.join("\n")}"
17
+
18
+
19
+ assert from_state.transitions_on_event[event].any?{|tr| tr.from == from_state && tr.to == to_state}, failure_msg
20
+ end
21
+
22
+ def assert_no_transition_on_event(statemachine, event, from_state, to_state)
23
+ from_state = statemachine.states[from_state]
24
+ to_state = statemachine.states[to_state]
25
+ event = statemachine.events[event]
26
+
27
+ assert_not_nil from_state
28
+ assert_not_nil to_state
29
+ assert_not_nil event
30
+
31
+ failure_msg = "#{statemachine} should not have a transition from #{from_state.name.inspect} to #{to_state.name.inspect} on event #{event.name.inspect}"
32
+
33
+ assert !from_state.transitions_on_event[event].any?{|tr| tr.from == from_state && tr.to == to_state}, failure_msg
34
+ end
35
+
36
+ def assert_transition_on_event_has_callback(statemachine, event, from_state, to_state, callback, callback_method = nil)
37
+ from_state = statemachine.states[from_state]
38
+ to_state = statemachine.states[to_state]
39
+ event = statemachine.events[event]
40
+
41
+ assert_transition_on_event(statemachine, event, from_state, to_state)
42
+
43
+ tr = from_state.transitions_on_event[event].find{|tr| tr.to == to_state}
44
+
45
+ failure_msg = "#{tr.to_s.inspect} does not have an #{callback.inspect} callback"
46
+
47
+ assert_not_nil tr.callbacks[callback], failure_msg
48
+
49
+ assert_equal callback_method, tr.callbacks[callback].callback if callback_method
50
+ end
51
+
52
+ def assert_transition_on_event_has_guard(statemachine, event, from_state, to_state, guard)
53
+ from_state = statemachine.states[from_state]
54
+ to_state = statemachine.states[to_state]
55
+ event = statemachine.events[event]
56
+
57
+ assert_transition_on_event(statemachine, event, from_state, to_state)
58
+
59
+ tr = from_state.transitions_on_event[event].find{|tr| tr.to == to_state}
60
+
61
+ failure_msg = "#{tr.to_s.inspect} does not have #{guard.inspect} as a guard condition"
62
+
63
+ assert tr.guards.collect{|g| g.callback}.include?(guard), failure_msg
64
+ end
65
+
66
+ def assert_transition_on_event_does_not_have_guard(statemachine, event, from_state, to_state, guard)
67
+ from_state = statemachine.states[from_state]
68
+ to_state = statemachine.states[to_state]
69
+ event = statemachine.events[event]
70
+
71
+ assert_transition_on_event(statemachine, event, from_state, to_state)
72
+
73
+ tr = from_state.transitions_on_event[event].find{|tr| tr.to == to_state}
74
+
75
+ failure_msg = "#{tr.to_s.inspect} should not have #{guard.inspect} as a guard condition"
76
+
77
+ assert !tr.guards.collect{|g| g.callback}.include?(guard), failure_msg
78
+ end
79
+ end
@@ -0,0 +1,5 @@
1
+ require 'test/unit'
2
+
3
+ $: << File.dirname(__FILE__)+'/../lib'
4
+
5
+ require 'golem'
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: golem_statemachine
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ version: "0.9"
10
+ platform: ruby
11
+ authors:
12
+ - Matt Zukowski
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-04-28 00:00:00 Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: activesupport
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: Adds finite state machine behaviour to Ruby classes. Meant as an alternative to acts_as_state_machine/AASM.
34
+ email:
35
+ - matt@roughest.net
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - README.rdoc
42
+ - MIT-LICENSE
43
+ files:
44
+ - .gitignore
45
+ - MIT-LICENSE
46
+ - README.rdoc
47
+ - Rakefile
48
+ - examples/document.rb
49
+ - examples/monster.rb
50
+ - examples/seminar.rb
51
+ - examples/seminar_enrollment.rb
52
+ - init.rb
53
+ - install.rb
54
+ - lib/golem.rb
55
+ - lib/golem/dsl/decision_def.rb
56
+ - lib/golem/dsl/event_def.rb
57
+ - lib/golem/dsl/state_def.rb
58
+ - lib/golem/dsl/state_machine_def.rb
59
+ - lib/golem/dsl/transition_def.rb
60
+ - lib/golem/model/callback.rb
61
+ - lib/golem/model/condition.rb
62
+ - lib/golem/model/event.rb
63
+ - lib/golem/model/state.rb
64
+ - lib/golem/model/state_machine.rb
65
+ - lib/golem/model/transition.rb
66
+ - lib/golem/util/element_collection.rb
67
+ - tasks/golem_statemachine_tasks.rake
68
+ - test/active_record_test.rb
69
+ - test/dsl_test.rb
70
+ - test/monster_test.rb
71
+ - test/problematic_test.rb
72
+ - test/seminar_test.rb
73
+ - test/statemachine_assertions.rb
74
+ - test/test.db
75
+ - test/test_helper.rb
76
+ - uninstall.rb
77
+ homepage: http://github.com/zuk/golem_statemachine
78
+ licenses: []
79
+
80
+ post_install_message:
81
+ rdoc_options:
82
+ - --quiet
83
+ - --title
84
+ - Golem Statmeachine Docs
85
+ - --opname
86
+ - index.html
87
+ - --line-numbers
88
+ - --main
89
+ - README.rdoc
90
+ - --inline-source
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.7.2
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: Adds finite state machine behaviour to Ruby classes.
118
+ test_files: []
119
+