ellington 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +14 -2
- data/Gemfile.lock +40 -0
- data/README.md +66 -17
- data/lib/ellington.rb +6 -4
- data/lib/ellington/attendant.rb +21 -0
- data/lib/ellington/conductor.rb +59 -0
- data/lib/ellington/connection.rb +11 -0
- data/lib/ellington/connection_list.rb +29 -0
- data/lib/ellington/errros.rb +22 -0
- data/lib/ellington/has_targets.rb +29 -0
- data/lib/ellington/line.rb +95 -0
- data/lib/ellington/line_info.rb +34 -0
- data/lib/ellington/line_list.rb +24 -0
- data/lib/ellington/logger.rb +11 -0
- data/lib/ellington/passenger.rb +67 -0
- data/lib/ellington/route.rb +114 -0
- data/lib/ellington/route_info.rb +25 -0
- data/lib/ellington/station.rb +88 -0
- data/lib/ellington/station_info.rb +11 -0
- data/lib/ellington/station_list.rb +24 -0
- data/lib/ellington/target.rb +25 -0
- data/lib/ellington/ticket.rb +22 -0
- data/lib/ellington/transition_info.rb +4 -0
- data/lib/ellington/unique_type_array.rb +39 -0
- data/lib/ellington/version.rb +1 -1
- data/test/attendant_test.rb +42 -0
- data/test/conductor_test.rb +32 -0
- data/test/example.rb +212 -0
- data/test/line_test.rb +95 -0
- data/test/passenger_test.rb +73 -0
- data/test/route_test.rb +51 -0
- data/test/station_test.rb +115 -0
- data/test/target_test.rb +54 -0
- data/test/test_helper.rb +6 -0
- data/test/ticket_test.rb +39 -0
- metadata +92 -14
- data/.gitignore +0 -17
- data/ellington.gemspec +0 -19
data/test/route_test.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
class RouteTest < MicroTest::Test
|
4
|
+
|
5
|
+
before do
|
6
|
+
@route = BasicMath.new
|
7
|
+
end
|
8
|
+
|
9
|
+
test "lines on class" do
|
10
|
+
assert @route.lines.length == 3
|
11
|
+
assert @route.lines[0].is_a?(Addition)
|
12
|
+
assert @route.lines[1].is_a?(Division)
|
13
|
+
assert @route.lines[2].is_a?(Multiplication)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "type of lines must be unique" do
|
17
|
+
begin
|
18
|
+
@route.lines << Addition.new
|
19
|
+
rescue Ellington::ListAlreadyContainsType => e
|
20
|
+
end
|
21
|
+
assert !e.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
test "lines are assigned route" do
|
25
|
+
@route.lines.each do |line|
|
26
|
+
assert line.route == BasicMath
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
test "goal" do
|
31
|
+
goals = @route.goal & [@route.lines[1].goal, @route.lines[2].goal].flatten
|
32
|
+
assert @route.goal.length == goals.length
|
33
|
+
end
|
34
|
+
|
35
|
+
test "fail_target" do
|
36
|
+
assert !@route.fail_target.empty?
|
37
|
+
assert((@route.fail_target & @route.pass_target).empty?)
|
38
|
+
expected = (@route.states.keys - @route.pass_target).delete_if do |state|
|
39
|
+
state.to_s =~ /\AERROR/
|
40
|
+
end
|
41
|
+
assert @route.fail_target == expected
|
42
|
+
end
|
43
|
+
|
44
|
+
test "connections" do
|
45
|
+
assert @route.connections.first.line == @route.lines[1]
|
46
|
+
assert @route.connections.first.states == @route.lines[0].pass_target
|
47
|
+
assert @route.connections.last.line == @route.lines[2]
|
48
|
+
assert @route.connections.last.states == @route.lines[0].fail_target
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
class StationTest < MicroTest::Test
|
4
|
+
|
5
|
+
before do
|
6
|
+
@route = BasicMath.new
|
7
|
+
@line = @route.lines.first
|
8
|
+
@station = @line.stations.first
|
9
|
+
@passenger = Ellington::Passenger.new(NumberWithHistory.new(0), @route)
|
10
|
+
@passenger.current_state = @route.initial_state
|
11
|
+
@passenger.lock
|
12
|
+
end
|
13
|
+
|
14
|
+
test "name" do
|
15
|
+
assert @station.name == "Add10::Addition"
|
16
|
+
end
|
17
|
+
|
18
|
+
test "state_name" do
|
19
|
+
assert @station.state_name(:foo) == "FOO Add10::Addition"
|
20
|
+
end
|
21
|
+
|
22
|
+
test "passed" do
|
23
|
+
assert @station.passed == "PASS Add10::Addition"
|
24
|
+
end
|
25
|
+
|
26
|
+
test "failed" do
|
27
|
+
assert @station.failed == "FAIL Add10::Addition"
|
28
|
+
end
|
29
|
+
|
30
|
+
test "errored" do
|
31
|
+
assert @station.errored == "ERROR Add10::Addition"
|
32
|
+
end
|
33
|
+
|
34
|
+
test "states keys" do
|
35
|
+
assert @station.states.keys == [
|
36
|
+
@station.passed,
|
37
|
+
@station.failed,
|
38
|
+
@station.errored
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
test "error state can transition to passed" do
|
43
|
+
assert @station.states.can_transition?(@station.errored => @station.passed)
|
44
|
+
end
|
45
|
+
|
46
|
+
test "error state can transition to failed" do
|
47
|
+
assert @station.states.can_transition?(@station.errored => @station.failed)
|
48
|
+
end
|
49
|
+
|
50
|
+
test "pass state is terminating" do
|
51
|
+
assert @station.states[@station.passed].nil?
|
52
|
+
assert !@station.states.can_transition?(@station.passed => @station.failed)
|
53
|
+
assert !@station.states.can_transition?(@station.passed => @station.errored)
|
54
|
+
end
|
55
|
+
|
56
|
+
test "fail state is terminating" do
|
57
|
+
assert @station.states[@station.failed].nil?
|
58
|
+
assert !@station.states.can_transition?(@station.failed => @station.passed)
|
59
|
+
assert !@station.states.can_transition?(@station.failed => @station.errored)
|
60
|
+
end
|
61
|
+
|
62
|
+
test "pass properly transitions passenger's state" do
|
63
|
+
@passenger.current_state = @route.initial_state
|
64
|
+
@station.pass @passenger
|
65
|
+
assert @passenger.current_state == @station.passed
|
66
|
+
end
|
67
|
+
|
68
|
+
test "fail properly transitions passenger's state" do
|
69
|
+
@passenger.current_state = @route.initial_state
|
70
|
+
@station.fail @passenger
|
71
|
+
assert @passenger.current_state == @station.failed
|
72
|
+
end
|
73
|
+
|
74
|
+
test "error properly transitions passenger's state" do
|
75
|
+
@passenger.current_state = @route.initial_state
|
76
|
+
@station.error @passenger
|
77
|
+
assert @passenger.current_state == @station.errored
|
78
|
+
end
|
79
|
+
|
80
|
+
test "can_engage? returns true for the expected inital state" do
|
81
|
+
@passenger.current_state = @route.initial_state
|
82
|
+
assert @station.can_engage?(@passenger)
|
83
|
+
end
|
84
|
+
|
85
|
+
test "can_engage? returns false for unexpected inital states" do
|
86
|
+
@passenger.current_state = @line.stations.last.passed
|
87
|
+
assert !@station.can_engage?(@passenger)
|
88
|
+
@passenger.current_state = :unexpected
|
89
|
+
assert !@station.can_engage?(@passenger)
|
90
|
+
end
|
91
|
+
|
92
|
+
test "engage" do
|
93
|
+
@passenger.current_state = @route.initial_state
|
94
|
+
@station.engage(@passenger, :pass => true)
|
95
|
+
assert @passenger.current_state == @station.passed
|
96
|
+
end
|
97
|
+
|
98
|
+
test "observers are notified after a station completes" do
|
99
|
+
observer = MicroMock.make.new
|
100
|
+
observer.attr :callbacks, []
|
101
|
+
observer.def :update do |info|
|
102
|
+
callbacks << info
|
103
|
+
end
|
104
|
+
@station.add_observer observer
|
105
|
+
@passenger.current_state = @route.initial_state
|
106
|
+
@station.call(@passenger, :pass => true)
|
107
|
+
assert observer.callbacks.length == 1
|
108
|
+
info = observer.callbacks.first
|
109
|
+
assert info.station == @station
|
110
|
+
assert info.passenger == @passenger
|
111
|
+
assert info.transition.old_state == @route.initial_state
|
112
|
+
assert info.transition.new_state == @station.passed
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
data/test/target_test.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
class TargetTest < MicroTest::Test
|
4
|
+
|
5
|
+
before do
|
6
|
+
@number = NumberWithHistory.new(0)
|
7
|
+
end
|
8
|
+
|
9
|
+
test "basic goal" do
|
10
|
+
goal = Ellington::Target.new(:finished)
|
11
|
+
assert goal.include?(:finished)
|
12
|
+
end
|
13
|
+
|
14
|
+
test "multiple states" do
|
15
|
+
goal = Ellington::Target.new(:one, :two, :three)
|
16
|
+
assert goal.include?(:one)
|
17
|
+
assert goal.include?(:two)
|
18
|
+
assert goal.include?(:three)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "not satisfied for nil passenger" do
|
22
|
+
goal = Ellington::Target.new(:finished)
|
23
|
+
assert !goal.satisfied?(nil)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "not satisfied for passenger in the wrong state" do
|
27
|
+
passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
|
28
|
+
passenger.current_state = :open
|
29
|
+
goal = Ellington::Target.new(:closed)
|
30
|
+
assert !goal.satisfied?(passenger)
|
31
|
+
end
|
32
|
+
|
33
|
+
test "satisfied for passenger in the right state" do
|
34
|
+
passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
|
35
|
+
passenger.current_state = :closed
|
36
|
+
goal = Ellington::Target.new(:closed)
|
37
|
+
assert goal.satisfied?(passenger)
|
38
|
+
end
|
39
|
+
|
40
|
+
test "satisfied for passenger in an expected state" do
|
41
|
+
passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
|
42
|
+
passenger.current_state = :two
|
43
|
+
goal = Ellington::Target.new(:one, :two, :three)
|
44
|
+
assert goal.satisfied?(passenger)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "not satisfied for passenger not in an expected state" do
|
48
|
+
passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
|
49
|
+
passenger.current_state = :four
|
50
|
+
goal = Ellington::Target.new(:one, :two, :three)
|
51
|
+
assert !goal.satisfied?(passenger)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/test/test_helper.rb
ADDED
data/test/ticket_test.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
require "digest"
|
3
|
+
|
4
|
+
class TicketTest < MicroTest::Test
|
5
|
+
|
6
|
+
before do
|
7
|
+
@route = BasicMath.new
|
8
|
+
@ticket = Ellington::Ticket.new(Ellington::Target.new(:closed),
|
9
|
+
:user_id => "458e9710-c1c4-495b-b25a-c622e893f6f7",
|
10
|
+
:debit_id => "b834fb69-2eb3-4e57-b313-16b863e91f74",
|
11
|
+
:credit_id => "9a670fce-4826-4a90-aaf7-a58738a4ce5b"
|
12
|
+
)
|
13
|
+
@passenger = Ellington::Passenger.new(0, @route, @ticket)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "basic ticket" do
|
17
|
+
assert @ticket[:user_id] == "458e9710-c1c4-495b-b25a-c622e893f6f7"
|
18
|
+
assert @ticket[:debit_id] == "b834fb69-2eb3-4e57-b313-16b863e91f74"
|
19
|
+
assert @ticket[:credit_id] == "9a670fce-4826-4a90-aaf7-a58738a4ce5b"
|
20
|
+
end
|
21
|
+
|
22
|
+
test "ticket id" do
|
23
|
+
assert @ticket.id == Digest::SHA256.hexdigest(@ticket.values.map(&:to_s).join)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "goal" do
|
27
|
+
assert @ticket.goal.to_a == [:closed]
|
28
|
+
end
|
29
|
+
|
30
|
+
test "goal is not achieved when passenger is not in the correct state" do
|
31
|
+
assert !@ticket.goal.satisfied?(@passenger)
|
32
|
+
end
|
33
|
+
|
34
|
+
test "goal is achieved when passenger is in the correct state" do
|
35
|
+
@passenger.current_state = :closed
|
36
|
+
assert @ticket.goal.satisfied?(@passenger)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ellington
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,92 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
13
|
-
dependencies:
|
14
|
-
|
12
|
+
date: 2013-02-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hero
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.1.7
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.1.7
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: state_jacket
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.0.7
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.0.7
|
46
|
+
description: ! "\n Ellington is a collection of simple concepts designed to bring
|
47
|
+
discipline, organization, and modularity to a project.\n\n The nomenclature is
|
48
|
+
taken from New York's subway system.\n We've found that using cohesive physical
|
49
|
+
metaphors helps people reason more clearly about the complexities of software.\n
|
50
|
+
\ The subway analogy isn't perfect but gets pretty close.\n\n The Ellington
|
51
|
+
architecture should only be applied after a good understanding of the problem domain
|
52
|
+
has been established.\n We recommend spiking a solution to learn your project's
|
53
|
+
requirements and then coming back to Ellington.\n "
|
15
54
|
email:
|
16
55
|
- natehop@gmail.com
|
17
56
|
executables: []
|
18
57
|
extensions: []
|
19
58
|
extra_rdoc_files: []
|
20
59
|
files:
|
21
|
-
- .
|
60
|
+
- lib/ellington/attendant.rb
|
61
|
+
- lib/ellington/conductor.rb
|
62
|
+
- lib/ellington/connection.rb
|
63
|
+
- lib/ellington/connection_list.rb
|
64
|
+
- lib/ellington/errros.rb
|
65
|
+
- lib/ellington/has_targets.rb
|
66
|
+
- lib/ellington/line.rb
|
67
|
+
- lib/ellington/line_info.rb
|
68
|
+
- lib/ellington/line_list.rb
|
69
|
+
- lib/ellington/logger.rb
|
70
|
+
- lib/ellington/passenger.rb
|
71
|
+
- lib/ellington/route.rb
|
72
|
+
- lib/ellington/route_info.rb
|
73
|
+
- lib/ellington/station.rb
|
74
|
+
- lib/ellington/station_info.rb
|
75
|
+
- lib/ellington/station_list.rb
|
76
|
+
- lib/ellington/target.rb
|
77
|
+
- lib/ellington/ticket.rb
|
78
|
+
- lib/ellington/transition_info.rb
|
79
|
+
- lib/ellington/unique_type_array.rb
|
80
|
+
- lib/ellington/version.rb
|
81
|
+
- lib/ellington.rb
|
22
82
|
- Gemfile
|
83
|
+
- Gemfile.lock
|
23
84
|
- LICENSE.txt
|
24
|
-
- README.md
|
25
85
|
- Rakefile
|
26
|
-
-
|
27
|
-
-
|
28
|
-
-
|
29
|
-
|
86
|
+
- README.md
|
87
|
+
- test/attendant_test.rb
|
88
|
+
- test/conductor_test.rb
|
89
|
+
- test/example.rb
|
90
|
+
- test/line_test.rb
|
91
|
+
- test/passenger_test.rb
|
92
|
+
- test/route_test.rb
|
93
|
+
- test/station_test.rb
|
94
|
+
- test/target_test.rb
|
95
|
+
- test/test_helper.rb
|
96
|
+
- test/ticket_test.rb
|
97
|
+
homepage: https://github.com/hopsoft/ellington
|
30
98
|
licenses: []
|
31
99
|
post_install_message:
|
32
100
|
rdoc_options: []
|
@@ -46,9 +114,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
114
|
version: '0'
|
47
115
|
requirements: []
|
48
116
|
rubyforge_project:
|
49
|
-
rubygems_version: 1.8.
|
117
|
+
rubygems_version: 1.8.25
|
50
118
|
signing_key:
|
51
119
|
specification_version: 3
|
52
|
-
summary:
|
53
|
-
|
54
|
-
|
120
|
+
summary: A framework for moving stateful objects through a complex series of business
|
121
|
+
rules.
|
122
|
+
test_files:
|
123
|
+
- test/attendant_test.rb
|
124
|
+
- test/conductor_test.rb
|
125
|
+
- test/example.rb
|
126
|
+
- test/line_test.rb
|
127
|
+
- test/passenger_test.rb
|
128
|
+
- test/route_test.rb
|
129
|
+
- test/station_test.rb
|
130
|
+
- test/target_test.rb
|
131
|
+
- test/test_helper.rb
|
132
|
+
- test/ticket_test.rb
|
data/.gitignore
DELETED
data/ellington.gemspec
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'ellington/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |gem|
|
7
|
-
gem.name = "ellington"
|
8
|
-
gem.version = Ellington::VERSION
|
9
|
-
gem.authors = ["Nathan Hopkins"]
|
10
|
-
gem.email = ["natehop@gmail.com"]
|
11
|
-
gem.description = %q{Write a gem description}
|
12
|
-
gem.summary = %q{Write a gem summary}
|
13
|
-
gem.homepage = ""
|
14
|
-
|
15
|
-
gem.files = `git ls-files`.split($/)
|
16
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = ["lib"]
|
19
|
-
end
|