symian 0.1.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.
@@ -0,0 +1,203 @@
1
+ require 'test_helper'
2
+
3
+ require 'symian/trace_collector'
4
+ require 'symian/incident'
5
+ require 'symian/support_group'
6
+ require 'symian/operator'
7
+ require 'symian/event'
8
+
9
+ require 'tempfile'
10
+
11
+
12
+ describe Symian::TraceCollector do
13
+
14
+ context 'backends' do
15
+
16
+ context 'with memory backend' do
17
+
18
+ it 'should be creatable' do
19
+ Symian::TraceCollector.new(:memory)
20
+ end
21
+
22
+ it 'should not mind attempts to save the trace' do
23
+ Symian::TraceCollector.new(:memory).save_and_close
24
+ end
25
+
26
+ end
27
+
28
+ context 'with YAML file backend' do
29
+
30
+ it 'should require a namefile for creation' do
31
+ lambda { Symian::TraceCollector.new(:yaml) }.must_raise ArgumentError
32
+ end
33
+
34
+ it 'should be creatable' do
35
+ tmpfile = Tempfile.new('reserved_for_testing')
36
+
37
+ Symian::TraceCollector.new(:yaml, file: tmpfile.path).save_and_close
38
+
39
+ tmpfile.close
40
+ tmpfile.unlink
41
+ end
42
+
43
+ it 'should allow to save the trace on the YAML file' do
44
+ tmpfile = Tempfile.new('reserved_for_testing')
45
+
46
+ Symian::TraceCollector.new(:yaml, file: tmpfile.path).save_and_close
47
+ File.size?(tmpfile.path).must_be :>, 0
48
+
49
+ tmpfile.close
50
+ tmpfile.unlink
51
+ end
52
+
53
+ it 'should correctly save trace information' do
54
+ # initialize stuff
55
+ now = Time.now
56
+ incs = [ Symian::Incident.new(1, now),
57
+ Symian::Incident.new(2, now + 1.hour),
58
+ Symian::Incident.new(3, now + 2.hours) ]
59
+ simulation = MiniTest::Mock.new
60
+ sgs = [ Symian::SupportGroup.new('SG1',
61
+ simulation,
62
+ { :distribution => :exponential, :mean => 5 },
63
+ { :number => 3, :workshift => :all_day_long }),
64
+ Symian::SupportGroup.new('SG2',
65
+ simulation,
66
+ { :distribution => :exponential, :mean => 10 },
67
+ { :number => 5, :workshift => :all_day_long }),
68
+ Symian::SupportGroup.new('SG3',
69
+ simulation,
70
+ { :distribution => :exponential, :mean => 15 },
71
+ { :number => 7, :workshift => :all_day_long }),
72
+ Symian::SupportGroup.new('SG4',
73
+ simulation,
74
+ { :distribution => :exponential, :mean => 20 },
75
+ { :number => 9, :workshift => :all_day_long }) ]
76
+
77
+ tmpfile = Tempfile.new('reserved_for_testing')
78
+
79
+ # create first trace collector
80
+ tc_1 = Symian::TraceCollector.new(:yaml, file: tmpfile.path)
81
+
82
+ # record trace data
83
+ tc_1.record_incidents(incs)
84
+ tc_1.record_support_groups(sgs)
85
+
86
+ # save data to file
87
+ tc_1.save_and_close
88
+
89
+ # load new trace collector from file
90
+ tc_2 = Symian::TraceCollector.new(:yaml, file: tmpfile.path)
91
+
92
+ # check loaded data
93
+ count = 0
94
+ tc_2.incidents.must_equal 3
95
+ tc_2.with_incidents do |i|
96
+ i.must_be_instance_of Symian::Incident
97
+ count += 1
98
+ end
99
+
100
+ # check loaded data
101
+ count = 0
102
+ tc_2.support_groups.must_equal 4
103
+ tc_2.with_support_groups do |sg|
104
+ sg.must_be_instance_of Symian::SupportGroup
105
+ count += 1
106
+ end
107
+
108
+ # cleanup
109
+ tmpfile.close
110
+ tmpfile.unlink
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+
118
+
119
+ context 'operations' do
120
+
121
+ let (:now) { Time.now }
122
+
123
+ let (:incs) {
124
+ [ Symian::Incident.new(1, now),
125
+ Symian::Incident.new(2, now + 1.hour),
126
+ Symian::Incident.new(3, now + 2.hours) ]
127
+ }
128
+
129
+ let (:tc) { Symian::TraceCollector.new(:memory) }
130
+
131
+ let (:simulation) { MiniTest::Mock.new }
132
+
133
+ let (:sgs) {
134
+ [ Symian::SupportGroup.new('SG1',
135
+ simulation,
136
+ { :distribution => :exponential, :mean => 5 },
137
+ { :number => 3, :workshift => :all_day_long }),
138
+ Symian::SupportGroup.new('SG2',
139
+ simulation,
140
+ { :distribution => :exponential, :mean => 10 },
141
+ { :number => 5, :workshift => :all_day_long }),
142
+ Symian::SupportGroup.new('SG3',
143
+ simulation,
144
+ { :distribution => :exponential, :mean => 15 },
145
+ { :number => 7, :workshift => :all_day_long }) ]
146
+ }
147
+
148
+ it 'should store a single incident' do
149
+ tc.incidents.must_equal 0
150
+ tc.record_incidents(incs[0])
151
+ tc.incidents.must_equal 1
152
+ end
153
+
154
+ it 'should store an array of incidents' do
155
+ tc.incidents.must_equal 0
156
+ tc.record_incidents(incs)
157
+ tc.incidents.must_equal 3
158
+ end
159
+
160
+ it 'should store a single support group' do
161
+ tc.support_groups.must_equal 0
162
+ tc.record_support_groups(sgs[0])
163
+ tc.support_groups.must_equal 1
164
+ end
165
+
166
+ it 'should store an array of support groups' do
167
+ tc.support_groups.must_equal 0
168
+ tc.record_support_groups(sgs)
169
+ tc.support_groups.must_equal 3
170
+ end
171
+
172
+ it 'should store a single event'
173
+
174
+ it 'should store an array of events'
175
+
176
+ it 'should allow evaluating a block for each stored incident' do
177
+ tc.record_incidents(incs)
178
+ tc.with_incidents do |i|
179
+ i.closure_time = now
180
+ end
181
+ tc.with_incidents do |i|
182
+ i.closure_time.must_equal now
183
+ end
184
+ end
185
+
186
+ it 'should allow considering stored incidents as an enumerable' do
187
+ tc.record_incidents(incs)
188
+ incs_arrived = tc.with_incidents.select{|i| i.arrival_time <= now }
189
+ incs_arrived.size.must_equal 1
190
+ incs_arrived.first.must_equal incs.first
191
+ end
192
+
193
+ it 'should allow evaluating a block for each stored support group'
194
+
195
+ it 'should allow considering stored support groups as an enumerable'
196
+
197
+ it 'should allow evaluating a block for each stored event'
198
+
199
+ it 'should allow considering stored events as an enumerable'
200
+
201
+ end
202
+
203
+ end
@@ -0,0 +1,88 @@
1
+ require 'test_helper'
2
+
3
+ require 'symian/transition_matrix'
4
+
5
+
6
+ describe Symian::TransitionMatrix do
7
+
8
+ let(:test_matrix) do
9
+ # <<-END.gsub(/^\s+/, '') # remove leading spaces
10
+ # From/To,SG01,SG02,SG03,Out
11
+ # In,1,2,3,4
12
+ # SG01,0,2,0,2
13
+ # SG02,10,0,50,40
14
+ # SG03,0,3,0,3
15
+ # END
16
+ "From/To,SG01,SG02,SG03,Out\n" \
17
+ "In,1,2,3,4\n" \
18
+ "SG01,0,2,0,2\n" \
19
+ "SG02,10,0,50,40\n" \
20
+ "SG03,0,3,0,3"
21
+ end
22
+
23
+ it 'should correctly load and process an escalation matrix' do
24
+ tm = Symian::TransitionMatrix.new(test_matrix)
25
+ tm.transition_probabilities.must_equal({
26
+ 'In' => [
27
+ { :sg_name => 'SG01', :escalations => 1, :probability => 0.1 },
28
+ { :sg_name => 'SG02', :escalations => 2, :probability => 0.3 },
29
+ { :sg_name => 'SG03', :escalations => 3, :probability => 0.6 },
30
+ { :sg_name => 'Out', :escalations => 4, :probability => 1.0 }
31
+ ],
32
+ 'SG01' => [
33
+ { :sg_name => 'SG02', :escalations => 2, :probability => 0.5 },
34
+ { :sg_name => 'Out', :escalations => 2, :probability => 1.0 }
35
+ ],
36
+ 'SG02' => [
37
+ { :sg_name => 'SG01', :escalations => 10, :probability => 0.1 },
38
+ { :sg_name => 'SG03', :escalations => 50, :probability => 0.6 },
39
+ { :sg_name => 'Out', :escalations => 40, :probability => 1.0 }
40
+ ],
41
+ 'SG03' => [
42
+ { :sg_name => 'SG02', :escalations => 3, :probability => 0.5 },
43
+ { :sg_name => 'Out', :escalations => 3, :probability => 1.0 }
44
+ ],
45
+ })
46
+ end
47
+
48
+ it 'should correctly print the matrix' do
49
+ tm = Symian::TransitionMatrix.new(test_matrix)
50
+ tm.to_s.must_equal test_matrix.chomp
51
+ end
52
+
53
+ it 'should correctly escalate incidents between existing and connected groups' do
54
+ tm = Symian::TransitionMatrix.new(test_matrix)
55
+ 1.upto(30) do
56
+ [ 'SG01', 'SG03', 'Out' ].must_include tm.escalation('SG02')
57
+ end
58
+ end
59
+
60
+ it 'should not escalate incidents from unexisting groups' do
61
+ tm = Symian::TransitionMatrix.new(test_matrix)
62
+ lambda { tm.escalation('UnexistingSG') }.must_raise ArgumentError
63
+ end
64
+
65
+ # it 'should not escalate incidents to unconnected groups' do
66
+ # end
67
+
68
+ it 'should correctly merge support groups' do
69
+ tm = Symian::TransitionMatrix.new(test_matrix)
70
+ tm.merge('SG01', 'SG03')
71
+ tm.transition_probabilities.must_equal({
72
+ 'In' => [
73
+ { :sg_name => 'SG02', :escalations => 2, :probability => 0.2 },
74
+ { :sg_name => 'Out', :escalations => 4, :probability => 0.6 },
75
+ { :sg_name => 'Merge_of_SG01_and_SG03', :escalations => 4, :probability => 1.0 }
76
+ ],
77
+ 'SG02' => [
78
+ { :sg_name => 'Out', :escalations => 40, :probability => 0.4 },
79
+ { :sg_name => 'Merge_of_SG01_and_SG03', :escalations => 60, :probability => 1.0 }
80
+ ],
81
+ 'Merge_of_SG01_and_SG03' => [
82
+ { :sg_name => 'SG02', :escalations => 5, :probability => 0.5 },
83
+ { :sg_name => 'Out', :escalations => 5, :probability => 1.0 }
84
+ ]
85
+ })
86
+ end
87
+
88
+ end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+
3
+ require 'symian/work_shift'
4
+
5
+
6
+ describe Symian::WorkShift do
7
+
8
+ # it "should require a work shift type" do
9
+ # lambda { Symian::WorkShift.new }.should raise_error(ArgumentError)
10
+ # end
11
+
12
+ # it "should require a valid work shift type" do
13
+ # lambda { Symian::WorkShift.new(:unknown_type) }.should raise_error(ArgumentError)
14
+ # end
15
+
16
+ describe 'a 24-hours workshift' do
17
+
18
+ let(:ws) { Symian::WorkShift.new(:all_day_long) }
19
+
20
+ it 'should be always active' do
21
+ # a = Symian::WorkShift.new(:all_day_long)
22
+ ws.active_at?(Time.now).must_equal true
23
+ # lambda { a.secs_to_begin_of_shift(Time.now) }.should raise_error(RuntimeError)
24
+ end
25
+
26
+ it 'should never finish' do
27
+ ws.secs_to_end_of_shift(Time.now).must_equal Symian::WorkShift::Infinity
28
+ end
29
+
30
+ it 'should have an infinite duration' do
31
+ ws.duration().must_equal Symian::WorkShift::Infinity
32
+ end
33
+
34
+ end
35
+
36
+ describe 'predefined workshifts' do
37
+ # it "should support predefined workshifts" do
38
+ # a = nil
39
+ # lambda { a = Symian::WorkShift.new(:predefined, :id => 1) }.should_not raise_error
40
+ # end
41
+ end
42
+
43
+ describe 'custom workshifts' do
44
+
45
+ describe 'an 8-hour custom workshift started 1 hour ago' do
46
+
47
+ let(:ws) do
48
+ now = Time.now
49
+ workshift_start = now.advance(:hours => -1)
50
+ workshift_end = now.advance(:hours => 7)
51
+ Symian::WorkShift.new(:custom,
52
+ :start_time => workshift_start,
53
+ :end_time => workshift_end)
54
+ end
55
+
56
+ it 'should be active' do
57
+ ws.active_at?(Time.now).must_equal true
58
+ end
59
+
60
+ it 'should end in 7 hours' do
61
+ ws.secs_to_end_of_shift(Time.now).must_equal 7.hours
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,5 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/spec'
3
+ require 'minitest-spec-context'
4
+
5
+ require 'symian'
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: symian
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mauro Tortonesi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ~>
17
+ - !ruby/object:Gem::Version
18
+ version: 4.0.0
19
+ name: activesupport
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.2.0
33
+ name: awesome_print
34
+ prerelease: false
35
+ type: :runtime
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 0.0.2
47
+ name: erv
48
+ prerelease: false
49
+ type: :runtime
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.2
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: 0.11.0
61
+ name: ice_nine
62
+ prerelease: false
63
+ type: :runtime
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.11.0
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: 1.6.2
75
+ name: bundler
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 1.6.2
83
+ - !ruby/object:Gem::Dependency
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ version: 10.1.1
89
+ name: rake
90
+ prerelease: false
91
+ type: :development
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 10.1.1
97
+ - !ruby/object:Gem::Dependency
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: 0.0.3
103
+ name: minitest-spec-context
104
+ prerelease: false
105
+ type: :development
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 0.0.3
111
+ description: A Decision Support Tool for the Performance Optimization of IT Support Organizations
112
+ email:
113
+ - mauro.tortonesi@unife.it
114
+ executables:
115
+ - symian
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - Gemfile
120
+ - LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - bin/symian
124
+ - lib/symian.rb
125
+ - lib/symian/configuration.rb
126
+ - lib/symian/cost_analyzer.rb
127
+ - lib/symian/event.rb
128
+ - lib/symian/generator.rb
129
+ - lib/symian/incident.rb
130
+ - lib/symian/operator.rb
131
+ - lib/symian/performance_analyzer.rb
132
+ - lib/symian/simulation.rb
133
+ - lib/symian/sorted_array.rb
134
+ - lib/symian/support/dsl_helper.rb
135
+ - lib/symian/support/yaml_io.rb
136
+ - lib/symian/support_group.rb
137
+ - lib/symian/trace_collector.rb
138
+ - lib/symian/transition_matrix.rb
139
+ - lib/symian/version.rb
140
+ - lib/symian/work_shift.rb
141
+ - symian.gemspec
142
+ - test/symian/configuration_test.rb
143
+ - test/symian/cost_analyzer_test.rb
144
+ - test/symian/generator_test.rb
145
+ - test/symian/incident_test.rb
146
+ - test/symian/operator_test.rb
147
+ - test/symian/reference_configuration.rb
148
+ - test/symian/support_group_test.rb
149
+ - test/symian/trace_collector_test.rb
150
+ - test/symian/transition_matrix_test.rb
151
+ - test/symian/work_shift_test.rb
152
+ - test/test_helper.rb
153
+ homepage: https://github.com/mtortonesi/symian
154
+ licenses:
155
+ - MIT
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - '>='
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.1.9
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: A support tool for strategic and business-driven decision making in the performance optimization of the IT incident management process
177
+ test_files:
178
+ - test/symian/configuration_test.rb
179
+ - test/symian/cost_analyzer_test.rb
180
+ - test/symian/generator_test.rb
181
+ - test/symian/incident_test.rb
182
+ - test/symian/operator_test.rb
183
+ - test/symian/reference_configuration.rb
184
+ - test/symian/support_group_test.rb
185
+ - test/symian/trace_collector_test.rb
186
+ - test/symian/transition_matrix_test.rb
187
+ - test/symian/work_shift_test.rb
188
+ - test/test_helper.rb