spekmachine 0.1

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.
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: