spekmachine 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ $:.unshift('lib')
2
+ require 'rubygems'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/contrib/rubyforgepublisher'
5
+ require 'rake/clean'
6
+ require 'rake/testtask'
7
+ require 'rake/rdoctask'
8
+
9
+ PKG_NAME = "spekmachine"
10
+ PKG_VERSION = '0.1'
11
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
12
+ PKG_FILES = FileList[ '[A-Z]*', 'lib/**/*.rb' ]
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = PKG_NAME
16
+ s.summary = "Stateful specs"
17
+ s.version = PKG_VERSION
18
+ s.description = <<-EOF
19
+ spekmachine is a modification of RSpec, (http://rspec.rubyforge.org/) which
20
+ uses a state machine to test all transitions. It uses the Chinese Postman
21
+ algorithm to find the shortest way through all transitions.
22
+ EOF
23
+ s.files = PKG_FILES.to_a
24
+ s.require_path = 'lib'
25
+ s.has_rdoc = false
26
+
27
+ s.require_path = 'lib'
28
+ s.autorequire = 'spekmachine'
29
+ s.bindir = "bin"
30
+ s.executables = ["spekm"]
31
+ s.author = "Michiel de Mare"
32
+ s.homepage = "http://persia.rubyforge.org"
33
+ s.rubyforge_project = "persia"
34
+ s.add_dependency 'rspec' , '>= 0.6.3'
35
+ end
36
+
37
+ Rake::GemPackageTask.new(spec) do |pkg|
38
+ pkg.need_zip = true
39
+ pkg.need_tar = true
40
+ end
data/bin/spekm ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require_gem 'rspec'
4
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/spekmachine") # better stack traces this way
5
+
6
+ $context_runner = ::Spec::Runner::OptionParser.create_context_runner(ARGV, false, STDERR, STDOUT)
7
+
8
+ # If ARGV is a glob, it will actually each over each one of the matching files.
9
+ ARGV.each do |file_or_dir|
10
+ if File.directory?(file_or_dir)
11
+ Dir["#{file_or_dir}/**/*.rb"].each do |file|
12
+ require file
13
+ end
14
+ else
15
+ require file_or_dir
16
+ end
17
+ end
18
+
19
+ $context_runner.run(true)
20
+
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Define a task library for running RSpec contexts.
4
+
5
+ require 'rake'
6
+ require 'rake/tasklib'
7
+
8
+ module Spec
9
+ module Rake
10
+
11
+ # A Rake task that runs a set of RSpec contexts.
12
+ #
13
+ # Example:
14
+ #
15
+ # Rake::SpecTask.new do |t|
16
+ # t.warning = true
17
+ # end
18
+ #
19
+ # This will create a task that can be run with:
20
+ #
21
+ # rake spec
22
+ #
23
+ class SpecTask < ::Rake::TaskLib
24
+
25
+ # Name of spec task. (default is :spec)
26
+ attr_accessor :name
27
+
28
+ # Array of directories to be added to $LOAD_PATH before running the
29
+ # specs. Defaults to ['<the absolute path to RSpec's lib directory>']
30
+ attr_accessor :libs
31
+
32
+ # If true, requests that the specs be run with the warning flag set.
33
+ # E.g. warning=true implies "ruby -w" used to run the specs. Defaults to false.
34
+ attr_accessor :warning
35
+
36
+ # Glob pattern to match spec files. (default is 'spec/spec*.rb')
37
+ attr_accessor :pattern
38
+
39
+ # Array of commandline options to pass to RSpec. Defaults to [].
40
+ attr_accessor :spec_opts
41
+
42
+ # Where RSpec's output is written. Defaults to STDOUT.
43
+ attr_accessor :out
44
+
45
+ # Whether or not to use RCov (default is false)
46
+ # See http://eigenclass.org/hiki.rb?rcov
47
+ attr_accessor :rcov
48
+
49
+ # Array of commandline options to pass to RCov. Defaults to ['--exclude', 'lib\/spec,bin\/spec'].
50
+ # Ignored if rcov=false
51
+ attr_accessor :rcov_opts
52
+
53
+ # Directory where the RCov report is written. Defaults to "coverage"
54
+ # Ignored if rcov=false
55
+ attr_accessor :rcov_dir
56
+
57
+ # Array of commandline options to pass to ruby. Defaults to [].
58
+ attr_accessor :ruby_opts
59
+
60
+ # Whether or not to fail Rake when an error occurs (typically when specs fail).
61
+ # Defaults to true.
62
+ attr_accessor :fail_on_error
63
+
64
+ # A message to print to stdout when there are failures.
65
+ attr_accessor :failure_message
66
+
67
+ # Explicitly define the list of spec files to be included in a
68
+ # spec. +list+ is expected to be an array of file names (a
69
+ # FileList is acceptable). If both +pattern+ and +spec_files+ are
70
+ # used, then the list of spec files is the union of the two.
71
+ def spec_files=(list)
72
+ @spec_files = list
73
+ end
74
+
75
+ # Create a specing task.
76
+ def initialize(name=:spec)
77
+ @name = name
78
+ @libs = [File.expand_path(File.dirname(__FILE__) + '/../../../lib')]
79
+ @pattern = nil
80
+ @spec_files = nil
81
+ @spec_opts = []
82
+ @warning = false
83
+ @ruby_opts = []
84
+ @out = nil
85
+ @fail_on_error = true
86
+ @rcov = false
87
+ @rcov_opts = ['--exclude', 'lib\/spec,bin\/spec']
88
+ @rcov_dir = "coverage"
89
+
90
+ yield self if block_given?
91
+ @pattern = 'spec/**/*_spek.rb' if @pattern.nil? && @spec_files.nil?
92
+ define
93
+ end
94
+
95
+ def define
96
+ #raise "No spec files found." if file_list.empty?
97
+ spec_script = File.expand_path(File.dirname(__FILE__) + '/../../../bin/spekm')
98
+
99
+ lib_path = @libs.join(File::PATH_SEPARATOR)
100
+ actual_name = Hash === name ? name.keys.first : name
101
+ unless ::Rake.application.last_comment
102
+ desc "Run RSpec for #{actual_name}" + (@rcov ? " using RCov" : "")
103
+ end
104
+ task @name do
105
+ RakeFileUtils.verbose(@verbose) do
106
+ ruby_opts = @ruby_opts.clone
107
+ ruby_opts.push( "-I\"#{lib_path}\"" )
108
+ ruby_opts.push( "-S rcov" ) if @rcov
109
+ ruby_opts.push( "-w" ) if @warning
110
+
111
+ redirect = @out.nil? ? "" : " > #{@out}"
112
+ # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- [spec_opts] examples
113
+ # or
114
+ # ruby [ruby_opts] -Ilib bin/spec [spec_opts] examples
115
+ begin
116
+ ruby(
117
+ ruby_opts.join(" ") + " " +
118
+ rcov_option_list +
119
+ (@rcov ? %[ -o "#{@rcov_dir}" ] : "") +
120
+ '"' + spec_script + '"' + " " +
121
+ (@rcov ? "-- " : "") +
122
+ spec_option_list + " " +
123
+ file_list.collect { |fn| %["#{fn}"] }.join(' ') + " " +
124
+ redirect
125
+ )
126
+ rescue => e
127
+ puts @failure_message if @failure_message
128
+ raise e if @fail_on_error
129
+ end
130
+ end
131
+ end
132
+
133
+ if @rcov
134
+ desc "Remove rcov products for #{actual_name}"
135
+ task paste("clobber_", actual_name) do
136
+ rm_r @rcov_dir rescue nil
137
+ end
138
+
139
+ clobber_task = paste("clobber_", actual_name)
140
+ task :clobber => [clobber_task]
141
+
142
+ task actual_name => clobber_task
143
+ end
144
+ self
145
+ end
146
+
147
+ def rcov_option_list # :nodoc:
148
+ return "" unless @rcov
149
+ ENV['RCOVOPTS'] || @rcov_opts.join(" ") || ""
150
+ end
151
+
152
+ def spec_option_list # :nodoc:
153
+ ENV['RSPECOPTS'] || @spec_opts.join(" ") || ""
154
+ end
155
+
156
+ def file_list # :nodoc:
157
+ if ENV['SPEC']
158
+ FileList[ ENV['SPEC'] ]
159
+ else
160
+ result = []
161
+ result += @spec_files.to_a if @spec_files
162
+ result += FileList[ @pattern ].to_a if @pattern
163
+ FileList[result]
164
+ end
165
+ end
166
+
167
+ end
168
+ end
169
+ end
170
+
@@ -0,0 +1,152 @@
1
+ module Spec
2
+ module Runner
3
+ class Context
4
+ module InstanceMethods
5
+ def initialize(name, desc, &context_block)
6
+ @context_id = name
7
+ @name = desc
8
+
9
+ @context_eval_module = Module.new
10
+ @context_eval_module.extend ContextEval::ModuleMethods
11
+ @context_eval_module.include ContextEval::InstanceMethods
12
+ before_context_eval
13
+ @context_eval_module.class_eval(&context_block)
14
+ end
15
+
16
+ def context_id
17
+ @context_id
18
+ end
19
+
20
+ def before_context_eval
21
+ end
22
+
23
+ def inherit(klass)
24
+ @context_eval_module.inherit klass
25
+ end
26
+
27
+ def include(mod)
28
+ @context_eval_module.include mod
29
+ end
30
+
31
+ def goto(name, &block)
32
+ @context_eval_module.goto(name, &block)
33
+ end
34
+
35
+ def setup(&block)
36
+ @context_eval_module.setup(&block)
37
+ end
38
+
39
+ def teardown(&block)
40
+ @context_eval_module.teardown(&block)
41
+ end
42
+
43
+ def specify(spec_name, &block)
44
+ @context_eval_module.specify(spec_name, &block)
45
+ end
46
+
47
+ def jump_to(name)
48
+ goto_parts[name].call
49
+ end
50
+
51
+ def goto_parts
52
+ @context_eval_module.goto_parts
53
+ end
54
+
55
+ def run(reporter, dry_run=false)
56
+ reporter.add_context(@name)
57
+
58
+ prepare_execution_context_class
59
+ specifications.each do |specification|
60
+ execution_context = execution_context_class.new(specification)
61
+ #@exec_context.instance_variables.each {|v|
62
+ # val = @exec_context.instance_variable_get(v)
63
+ # execution_context.instance_variable_set v, val
64
+ #}
65
+ specification.run(reporter, nil, nil, dry_run, execution_context)
66
+ end
67
+ end
68
+
69
+ def number_of_specs
70
+ specifications.length
71
+ end
72
+
73
+ def matches? name, matcher=nil
74
+ matcher ||= SpecMatcher.new name, @name
75
+ specifications.each do |spec|
76
+ return true if spec.matches_matcher? matcher
77
+ end
78
+ return false
79
+ end
80
+
81
+ def run_single_spec name
82
+ return if @name == name
83
+ matcher = SpecMatcher.new name, @name
84
+ specifications.reject! do |spec|
85
+ !spec.matches_matcher? matcher
86
+ end
87
+ end
88
+
89
+ def methods
90
+ my_methods = super
91
+ my_methods |= @context_eval_module.methods
92
+ my_methods
93
+ end
94
+
95
+ protected
96
+
97
+ def method_missing(*args)
98
+ @context_eval_module.method_missing(*args)
99
+ end
100
+
101
+ def specifications
102
+ @context_eval_module.send :specifications
103
+ end
104
+
105
+ def setup_block
106
+ @context_eval_module.send :setup_block
107
+ end
108
+
109
+ def teardown_block
110
+ @context_eval_module.send :teardown_block
111
+ end
112
+
113
+ def setup_parts
114
+ @context_eval_module.send :setup_parts
115
+ end
116
+
117
+ def teardown_parts
118
+ @context_eval_module.send :teardown_parts
119
+ end
120
+
121
+ def prepare_execution_context_class
122
+ weave_in_context_modules
123
+ execution_context_class
124
+ end
125
+
126
+ def weave_in_context_modules
127
+ mods = context_modules
128
+ context_eval_module = @context_eval_module
129
+ execution_context_class.class_eval do
130
+ include context_eval_module
131
+ mods.each do |mod|
132
+ include mod
133
+ end
134
+ end
135
+ end
136
+
137
+ def context_modules
138
+ @context_eval_module.send :context_modules
139
+ end
140
+
141
+ def execution_context_class
142
+ @context_eval_module.send :execution_context_class
143
+ end
144
+
145
+ def context_superclass
146
+ @context_eval_module.send :context_superclass
147
+ end
148
+ end
149
+ include InstanceMethods
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,121 @@
1
+ module Spec
2
+ module Runner
3
+ module ContextEval
4
+ module ModuleMethods
5
+ def inherit(klass)
6
+ @context_superclass = klass
7
+ derive_execution_context_class_from_context_superclass
8
+ end
9
+
10
+ def include(mod)
11
+ context_modules << mod
12
+ end
13
+
14
+ def setup(&block)
15
+ setup_parts << block
16
+ end
17
+
18
+ def teardown(&block)
19
+ teardown_parts << block
20
+ end
21
+
22
+ def goto(name, &block)
23
+ goto_parts[name] = block
24
+ end
25
+
26
+ def specify(spec_name, &block)
27
+ specifications << Specification.new(spec_name, &block)
28
+ end
29
+
30
+ def methods
31
+ my_methods = super
32
+ my_methods |= context_superclass.methods
33
+ my_methods
34
+ end
35
+
36
+ def goto_parts
37
+ @goto_parts ||= {}
38
+ end
39
+
40
+ protected
41
+
42
+ def method_missing(method_name, *args)
43
+ if context_superclass.respond_to?(method_name)
44
+ return execution_context_class.send(method_name, *args)
45
+ end
46
+ super
47
+ end
48
+
49
+ def specifications
50
+ @specifications ||= []
51
+ end
52
+
53
+ def setup_parts
54
+ @setup_parts ||= []
55
+ end
56
+
57
+ def teardown_parts
58
+ @teardown_parts ||= []
59
+ end
60
+
61
+ def setup_block
62
+ parts = setup_parts.dup
63
+
64
+ setup_method = begin
65
+ context_superclass.instance_method(:setup)
66
+ rescue
67
+ nil
68
+ end
69
+ parts.unshift setup_method if setup_method
70
+ create_block_from_parts(parts)
71
+ end
72
+
73
+ def teardown_block
74
+ parts = teardown_parts.dup
75
+
76
+ teardown_method = begin
77
+ context_superclass.instance_method(:teardown)
78
+ rescue
79
+ nil
80
+ end
81
+ parts.unshift teardown_method if teardown_method
82
+ create_block_from_parts(parts)
83
+ end
84
+
85
+ def create_block_from_parts(parts)
86
+ proc do
87
+ parts.each do |part|
88
+ if part.is_a?(UnboundMethod)
89
+ puts part.inspect
90
+ part.bind(self).call
91
+ else
92
+ instance_exec(&part)
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def execution_context_class
99
+ @execution_context_class ||= derive_execution_context_class_from_context_superclass
100
+ end
101
+
102
+ def derive_execution_context_class_from_context_superclass
103
+ @execution_context_class = Class.new(context_superclass)
104
+ @execution_context_class.class_eval do
105
+ include ::Spec::Runner::ExecutionContext::InstanceMethods
106
+ end
107
+ end
108
+
109
+ def context_superclass
110
+ @context_superclass ||= Object
111
+ end
112
+
113
+ def context_modules
114
+ @context_modules ||= []
115
+ end
116
+ end
117
+ module InstanceMethods
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,62 @@
1
+ #require File.dirname(__FILE__) + '/../../spekmachine'
2
+
3
+ module Spec
4
+ module Runner
5
+ class ContextRunner
6
+ attr_reader :standalone
7
+
8
+ def initialize(reporter, standalone, dry_run, single_spec=nil)
9
+ @contexts = []
10
+ @reporter = reporter
11
+ @standalone = standalone
12
+ @dry_run = dry_run
13
+ @single_spec = single_spec
14
+ end
15
+
16
+ def set_start(name, block)
17
+ @start_name = name
18
+ @setup = block
19
+ end
20
+
21
+ def add_context(context)
22
+ return if !@single_spec.nil? unless context.matches?(@single_spec)
23
+ context.run_single_spec @single_spec if context.matches?(@single_spec)
24
+ @contexts << context
25
+ end
26
+
27
+ def create_path(ctxMap)
28
+ g = CPP.new
29
+ @contexts.each do |c|
30
+ c.goto_parts.keys.each {|dest| g.addArc(nil, c.context_id, dest) }
31
+ end
32
+ g.solve
33
+ mp = g.printCPT(g.convert_to_index(@start_name)).map {|arcLabel, from, to| [g.convert(from), g.convert(to)] }
34
+ mp.map {|from, to| [ctxMap[from], to] }
35
+ end
36
+
37
+ def run(exit_when_done)
38
+ raise unless @setup
39
+ @setup.call
40
+ cm = {}
41
+ @contexts.each {|c| cm[c.context_id] = c }
42
+ @reporter.start(number_of_specs)
43
+ path = create_path(cm)
44
+ path.each do |ctx, dest|
45
+ ctx.run(@reporter, @dry_run)
46
+ ctx.jump_to dest
47
+ end
48
+ @reporter.end
49
+ failure_count = @reporter.dump
50
+ if(exit_when_done)
51
+ exit_code = (failure_count == 0) ? 0 : 1
52
+ exit(exit_code)
53
+ end
54
+ end
55
+
56
+ def number_of_specs
57
+ @contexts.inject(0) {|sum, context| sum + context.number_of_specs}
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,19 @@
1
+ module Kernel
2
+ def setup(name, &block)
3
+ runner = context_runner
4
+ runner.set_start(name, block)
5
+ end
6
+
7
+ def context(name, desc, &block)
8
+ context = Spec::Runner::Context.new(name, desc, &block)
9
+ runner = context_runner
10
+ runner.add_context(context)
11
+ runner.run(false) if runner.standalone
12
+ end
13
+
14
+ private
15
+
16
+ def context_runner
17
+ $context_runner ||= ::Spec::Runner::OptionParser.create_context_runner(ARGV.dup, true, STDERR, STDOUT)
18
+ end
19
+ end
@@ -0,0 +1,213 @@
1
+ class CPP
2
+ attr_reader :c, :path
3
+ def initialize
4
+ @delta = Hash.new(0)
5
+ @defined = Hash.new {|h,k|h[k] = {}}
6
+ @label = Hash.new {|h,k|h[k] = {}}
7
+ @c = Hash.new {|h,k|h[k] = Hash.new(0)}
8
+ @f = Hash.new {|h,k|h[k] = Hash.new(0.0)}
9
+ @pos = []
10
+ @neg = []
11
+ @arcs = Hash.new {|h,k|h[k] = Hash.new(0) }
12
+ @cheapestLabel = Hash.new {|h,k|h[k] = {}}
13
+ @path = Hash.new {|h,k|h[k] = {}}
14
+ @basicCost = 0;
15
+ end
16
+
17
+ def solve
18
+ leastCostPaths
19
+ checkValid
20
+ findUnbalanced
21
+ findFeasible
22
+ loop do break unless improvements end
23
+ end
24
+
25
+ def convert(index)
26
+ @nodeList[index]
27
+ end
28
+
29
+ def convert_to_index(name)
30
+ @nodeMap[name]
31
+ end
32
+
33
+ def updateMap(a)
34
+ @nodeList ||= []
35
+ @nodeMap ||= {}
36
+ if @nodeMap[a]
37
+ u = @nodeMap[a]
38
+ else
39
+ u = @nodeList.size
40
+ @nodeMap[a] = u
41
+ @nodeList << a
42
+ end
43
+ u
44
+ end
45
+
46
+ def addArc(lab, a, b, cost = 1)
47
+ u = updateMap a
48
+ v = updateMap b
49
+ @n = @nodeList.size
50
+ @label[u][v] = [] if !@defined[u][v]
51
+ @label[u][v] << lab
52
+ @basicCost += cost
53
+ if !@defined[u][v] or @c[u][v] > cost
54
+ @c[u][v] = cost
55
+ @cheapestLabel[u][v] = lab
56
+ @defined[u][v] = true
57
+ @path[u][v] = v
58
+ end
59
+ @arcs[u][v] += 1
60
+ @delta[u] += 1
61
+ @delta[v] -= 1;
62
+ self
63
+ end
64
+
65
+ def leastCostPaths
66
+ @n.times do |k|
67
+ @n.times do |i|
68
+ if @defined[i][k]
69
+ @n.times do |j|
70
+ if @defined[k][j] and (!@defined[i][j] || @c[i][j] > @c[i][k]+@c[k][j])
71
+ @path[i][j] = @path[i][k];
72
+ @c[i][j] = @c[i][k]+@c[k][j];
73
+ @defined[i][j] = true;
74
+ return if i == j and @c[i][j] < 0
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ def checkValid
83
+ @n.times do |i|
84
+ @n.times do |j|
85
+ raise "Graph is not strongly connected for #{i} and #{j}" if !@defined[i][j]
86
+ end
87
+ raise "Graph has a negative cycle" if( @c[i][i] < 0 )
88
+ end
89
+ end
90
+
91
+ def cost
92
+ @basicCost + phi
93
+ end
94
+
95
+ def phi
96
+ phi = 0.0
97
+ @n.times do |i|
98
+ @n.times do |j|
99
+ phi += @c[i][j]*@f[i][j];
100
+ end
101
+ end
102
+ phi
103
+ end
104
+
105
+ def findUnbalanced
106
+ nn = np = 0
107
+
108
+ @n.times do |i|
109
+ nn += 1 if @delta[i] < 0
110
+ np += 1 if @delta[i] > 0
111
+ end
112
+
113
+ @neg = []
114
+ @pos = []
115
+ nn = np = 0;
116
+ @n.times do |i|
117
+ @neg[nn] = i and nn += 1 if @delta[i] < 0
118
+ @pos[np] = i and np += 1 if @delta[i] > 0
119
+ end
120
+ end
121
+
122
+ def findFeasible
123
+ @neg.length.times do |u|
124
+ i = @neg[u];
125
+ @pos.length.times do |v|
126
+ j = @pos[v];
127
+ @f[i][j] = -@delta[i] < @delta[j] ? -@delta[i] : @delta[j];
128
+ @delta[i] += @f[i][j];
129
+ @delta[j] -= @f[i][j];
130
+ end
131
+ end
132
+ end
133
+
134
+ def improvements
135
+ residual = CPP.new
136
+ @neg.length.times do |u|
137
+ i = @neg[u]
138
+ @pos.length.times do |v|
139
+ j = @pos[v]
140
+ residual.addArc(nil, i, j, @c[i][j])
141
+ residual.addArc(nil, j, i, -@c[i][j]) if @f[i][j] != 0
142
+ end
143
+ end
144
+ residual.leastCostPaths()
145
+ @n.times do |i|
146
+ if residual.c[i][i] < 0
147
+ k = 0
148
+ kunset = true;
149
+ u = i
150
+ loop do
151
+ v = residual.path[u][i];
152
+ if residual.c[u][v] < 0 and (kunset || k > @f[v][u])
153
+ k = @f[v][u]
154
+ kunset = false
155
+ end
156
+ break if (u = v) == i
157
+ end
158
+ u = i;
159
+ loop do
160
+ v = residual.path[u][i];
161
+ if residual.c[u][v] < 0
162
+ @f[v][u] -= k;
163
+ else
164
+ @f[u][v] += k;
165
+ end
166
+ return true if (u = v) == i
167
+ end
168
+ end
169
+ end
170
+ false;
171
+ end
172
+
173
+ def findPath(from)
174
+ ((0...@n).detect {|i| @f[from][i] > 0 }) or -1
175
+ end
176
+
177
+ def printCPT(startVertex)
178
+ result = []
179
+ v = startVertex;
180
+
181
+ loop do
182
+ u = v;
183
+ if (v = findPath(u)) != -1
184
+ @f[u][v] -= 1;
185
+ while u != v do
186
+ p = @path[u][v];
187
+ result << [@cheapestLabel[u][p], u, p]
188
+ u = p
189
+ end
190
+ else
191
+ bridgeVertex = @path[u][startVertex];
192
+ if @arcs[u][bridgeVertex] == 0
193
+ return result
194
+ end
195
+ v = bridgeVertex;
196
+ @n.times do |i|
197
+ if i != bridgeVertex && @arcs[u][i] > 0
198
+ v = i;
199
+ break;
200
+ end
201
+ end
202
+ @arcs[u][v] -= 1;
203
+ result << [@label[u][v][@arcs[u][v]], u, v]
204
+ end
205
+ end
206
+ raise 'cant get here'
207
+ end
208
+ end
209
+
210
+ # g = CPP.new()
211
+ # g.addArc("a", :a, :b).addArc("b", :a, :c).addArc("c", :b, :c) .addArc("d", :b, :d).addArc("e", :c, :d).addArc("f", :d, :a)
212
+ # g.solve()
213
+ # puts g.printCPT(0).map {|a,b,c| "Take arc #{a} from #{b} to #{c}"}.join("\n")
@@ -0,0 +1,5 @@
1
+ require 'spekmachine/runner/context'
2
+ require 'spekmachine/runner/context_eval'
3
+ require 'spekmachine/runner/context_runner'
4
+ require 'spekmachine/runner/kernel_ext'
5
+ require 'spekmachine/runner/path'
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: spekmachine
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2006-09-14 00:00:00 +02:00
8
+ summary: Stateful specs
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage: http://persia.rubyforge.org
13
+ rubyforge_project: persia
14
+ description: spekmachine is a modification of RSpec, (http://rspec.rubyforge.org/) which uses a state machine to test all transitions. It uses the Chinese Postman algorithm to find the shortest way through all transitions.
15
+ autorequire: spekmachine
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Michiel de Mare
30
+ files:
31
+ - Rakefile
32
+ - lib/spekmachine.rb
33
+ - lib/spekmachine/rake/spectask.rb
34
+ - lib/spekmachine/runner/context.rb
35
+ - lib/spekmachine/runner/context_eval.rb
36
+ - lib/spekmachine/runner/context_runner.rb
37
+ - lib/spekmachine/runner/kernel_ext.rb
38
+ - lib/spekmachine/runner/path.rb
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables:
46
+ - spekm
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies:
52
+ - !ruby/object:Gem::Dependency
53
+ name: rspec
54
+ version_requirement:
55
+ version_requirements: !ruby/object:Gem::Version::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.6.3
60
+ version: