grosser-autotest 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ module Autotest::Menu
4
+ WINDOZE = /win32/ =~ RUBY_PLATFORM unless defined? WINDOZE
5
+
6
+ if WINDOZE then
7
+ require "Win32API"
8
+ def self.getchar
9
+ Win32API.new("crtdll", "_getch", [], "L").Call
10
+ end
11
+ else
12
+ STTY_SAVE_STATE=`stty -g`
13
+ def self.getchar
14
+ system 'stty raw echo'
15
+ STDIN.getc
16
+ ensure
17
+ system "stty '#{STTY_SAVE_STATE}'"
18
+ end
19
+ end
20
+
21
+ def self.menu(choices)
22
+ result = nil
23
+ choices.sort.each do |c, desc|
24
+ puts "#{c.chr}: #{desc}"
25
+ end
26
+ until choices[result]
27
+ print "menu> "
28
+ result = getchar
29
+ print " invalid input" unless choices[result]
30
+ puts
31
+ end
32
+ result
33
+ end
34
+
35
+ Autotest.add_hook(:interrupt) do |at|
36
+ $stderr.puts "menu"
37
+ case menu ?q => "quit", ?c => "continue", ?r => "restart"
38
+ when ?c
39
+ true
40
+ when ?r
41
+ at.reset
42
+ true
43
+ when ?q
44
+ at.wants_to_quit = true
45
+ true
46
+ else
47
+ false
48
+ end
49
+ # puts "you chose #{c.chr}"
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::Migrate
4
+ Autotest.add_hook(:run) do |autotest|
5
+ system "rake db:migrate" if autotest.class.to_s == "RailsAutotest"
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ module Autotest::Notify
2
+ def self.notify(title, message, priority='critical')
3
+ icon = if priority == 'critical'
4
+ 'dialog-error'
5
+ else
6
+ 'dialog-information'
7
+ end
8
+ system "notify-send -u #{priority} -t 10000 -i #{icon} '#{title}' '#{message.inspect}'"
9
+ end
10
+
11
+ Autotest.add_hook :red do |at|
12
+ tests = 0
13
+ assertions = 0
14
+ failures = 0
15
+ errors = 0
16
+ at.results.scan(/(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/) do |t, a, f, e|
17
+ tests += t.to_i
18
+ assertions += a.to_i
19
+ failures += f.to_i
20
+ errors += e.to_i
21
+ end
22
+ message = "%d tests, %d assertions, %d failures, %d errors" %
23
+ [tests, assertions, failures, errors]
24
+ notify("Tests Failed", message)
25
+ end
26
+
27
+ Autotest.add_hook :green do |at|
28
+ notify("Tests Passed", "Outstanding tests passed", 'low') if at.tainted
29
+ end
30
+
31
+ Autotest.add_hook :all do |at|_hook
32
+ notify("autotest", "Tests have fully passed", 'low')
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ ##
2
+ # this is for autotest plugin developers only...
3
+
4
+ module Autotest::Once
5
+ Autotest.add_hook :ran_command do |at|
6
+ exit 0
7
+ end
8
+ end
9
+
@@ -0,0 +1,83 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'osx/cocoa'
4
+ include Math
5
+ include OSX
6
+
7
+ OSX::NSBundle.bundleWithPath(File.expand_path("~/Library/Frameworks/Aquaterm.framework")).load
8
+ OSX.ns_import :AQTAdapter
9
+
10
+ class Autotest::Pretty
11
+ BLACK = 0
12
+ WHITE = 1
13
+ RED = 2
14
+ GREEN = 3
15
+ GRAY = 4
16
+
17
+ def initialize
18
+ @past = []
19
+
20
+ @adapter = AQTAdapter.alloc.init
21
+ @adapter.openPlotWithIndex 1
22
+ @adapter.setPlotSize([122,122])
23
+ @adapter.setPlotTitle("Autotest Status")
24
+
25
+ @adapter.setColormapEntry_red_green_blue(0, 0.0, 0.0, 0.0) # black
26
+ @adapter.setColormapEntry_red_green_blue(1, 1.0, 1.0, 1.0) # white
27
+ @adapter.setColormapEntry_red_green_blue(2, 1.0, 0.0, 0.0) # red
28
+ @adapter.setColormapEntry_red_green_blue(3, 0.0, 1.0, 0.0) # green
29
+ @adapter.setColormapEntry_red_green_blue(4, 0.7, 0.7, 0.7) # gray
30
+
31
+ draw
32
+ end
33
+
34
+ def draw
35
+ @past.shift if @past.size > 100
36
+
37
+ @adapter.takeColorFromColormapEntry(@past.last ? GREEN : RED)
38
+ @adapter.addFilledRect([0, 0, 122, 122])
39
+
40
+ @adapter.takeColorFromColormapEntry(BLACK)
41
+ @adapter.addFilledRect([10, 10, 102, 102])
42
+
43
+ @adapter.takeColorFromColormapEntry(GRAY)
44
+ @adapter.addFilledRect([11, 11, 100, 100])
45
+
46
+ @adapter.takeColorFromColormapEntry(0)
47
+
48
+ @past.each_with_index do |passed,i|
49
+ x = i % 10
50
+ y = i / 10
51
+
52
+ @adapter.takeColorFromColormapEntry(passed ? GREEN : RED)
53
+ @adapter.addFilledRect([x*10+11, y*10+11, 10, 10])
54
+ end
55
+ @adapter.renderPlot
56
+ end
57
+
58
+ def pass
59
+ @past.push true
60
+ draw
61
+ end
62
+
63
+ def fail
64
+ @past.push false
65
+ draw
66
+ end
67
+
68
+ def close
69
+ @adapter.closePlot
70
+ end
71
+ end
72
+
73
+ unless $TESTING then
74
+ board = Autotest::Pretty.new
75
+
76
+ Autotest.add_hook :red do |at|
77
+ board.fail unless $TESTING
78
+ end
79
+
80
+ Autotest.add_hook :green do |at|
81
+ board.pass unless $TESTING
82
+ end
83
+ end
@@ -0,0 +1,81 @@
1
+ require 'autotest'
2
+
3
+ class Autotest::Rails < Autotest
4
+
5
+ def initialize # :nodoc:
6
+ super
7
+
8
+ add_exception %r%^\./(?:db|doc|log|public|script|tmp|vendor)%
9
+
10
+ clear_mappings
11
+
12
+ self.add_mapping(/^lib\/.*\.rb$/) do |filename, _|
13
+ impl = File.basename(filename, '.rb')
14
+ files_matching %r%^test/unit/#{impl}_test.rb$%
15
+ # TODO: (unit|functional|integration) maybe?
16
+ end
17
+
18
+ add_mapping %r%^test/fixtures/(.*)s.yml% do |_, m|
19
+ ["test/unit/#{m[1]}_test.rb",
20
+ "test/controllers/#{m[1]}_controller_test.rb",
21
+ "test/views/#{m[1]}_view_test.rb",
22
+ "test/functional/#{m[1]}_controller_test.rb"]
23
+ end
24
+
25
+ add_mapping %r%^test/(unit|integration|controllers|views|functional)/.*rb$% do |filename, _|
26
+ filename
27
+ end
28
+
29
+ add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
30
+ "test/unit/#{m[1]}_test.rb"
31
+ end
32
+
33
+ add_mapping %r%^app/helpers/application_helper.rb% do
34
+ files_matching %r%^test/(views|functional)/.*_test\.rb$%
35
+ end
36
+
37
+ add_mapping %r%^app/helpers/(.*)_helper.rb% do |_, m|
38
+ if m[1] == "application" then
39
+ files_matching %r%^test/(views|functional)/.*_test\.rb$%
40
+ else
41
+ ["test/views/#{m[1]}_view_test.rb",
42
+ "test/functional/#{m[1]}_controller_test.rb"]
43
+ end
44
+ end
45
+
46
+ add_mapping %r%^app/views/(.*)/% do |_, m|
47
+ ["test/views/#{m[1]}_view_test.rb",
48
+ "test/functional/#{m[1]}_controller_test.rb"]
49
+ end
50
+
51
+ add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
52
+ if m[1] == "application" then
53
+ files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
54
+ else
55
+ ["test/controllers/#{m[1]}_test.rb",
56
+ "test/functional/#{m[1]}_test.rb"]
57
+ end
58
+ end
59
+
60
+ add_mapping %r%^app/views/layouts/% do
61
+ "test/views/layouts_view_test.rb"
62
+ end
63
+
64
+ add_mapping %r%^config/routes.rb$% do # FIX:
65
+ files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
66
+ end
67
+
68
+ add_mapping %r%^test/test_helper.rb|config/((boot|environment(s/test)?).rb|database.yml)% do
69
+ files_matching %r%^test/(unit|controllers|views|functional)/.*_test\.rb$%
70
+ end
71
+ end
72
+
73
+ # Convert the pathname s to the name of class.
74
+ def path_to_classname(s)
75
+ sep = File::SEPARATOR
76
+ f = s.sub(/^test#{sep}((unit|functional|integration|views|controllers|helpers)#{sep})?/, '').sub(/\.rb$/, '').split(sep)
77
+ f = f.map { |path| path.split(/_/).map { |seg| seg.capitalize }.join }
78
+ f = f.map { |path| path =~ /Test$/ ? path : "#{path}Test" }
79
+ f.join('::')
80
+ end
81
+ end
@@ -0,0 +1,22 @@
1
+ module Autotest::RCov
2
+ @@command, @@pattern = "rcov", "test/*.rb"
3
+
4
+ def self.command= o
5
+ @@command = o
6
+ end
7
+
8
+ def self.pattern= o
9
+ @@pattern = o
10
+ end
11
+
12
+ Autotest.add_hook :all_good do |at|
13
+ system "rake #{@@command} PATTERN=#{@@pattern}"
14
+ end
15
+
16
+ Autotest.add_hook :initialize do |at|
17
+ at.add_exception 'coverage'
18
+ at.add_exception 'coverage.info'
19
+ false
20
+ end
21
+ end
22
+
@@ -0,0 +1,21 @@
1
+ # -*- ruby -*-
2
+
3
+ # special thanks to Pat Eyler, Sean Carley, and Rob Sanheim
4
+ # and to Peter Havens for rspec patches
5
+ module Autotest::RedGreen
6
+ BAR = "=" * 78
7
+ REDCODE = 31
8
+ GREENCODE = 32
9
+
10
+ Autotest.add_hook :ran_command do |at|
11
+ green = case at.results.last
12
+ when /^.* (\d+) failures, (\d+) errors$/ # Test::Unit
13
+ ($1 == "0" and $2 == "0")
14
+ when /^\d+\s+examples?,\s+(\d+)\s+failure/ # RSpec
15
+ ($1 == "0")
16
+ end
17
+
18
+ code = green ? GREENCODE : REDCODE
19
+ puts "\e[#{ code }m#{ BAR }\e[0m\n\n" unless green.nil?
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Autotest::Restart
2
+ Autotest.add_hook :updated do |at, *args|
3
+ if args.flatten.include? ".autotest" then
4
+ warn "Detected change to .autotest, restarting"
5
+ cmd = "autotest"
6
+ cmd << " -v" if $v
7
+
8
+ exec cmd
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ require 'code_statistics'
2
+ require 'rbosa'
3
+
4
+ module Autotest::Shame
5
+ @@chat_app = :adium
6
+
7
+ def self.chat_app= o
8
+ @@chat_app = o
9
+ end
10
+
11
+ # Until the rails team learns how to write modular code... I must steal :/
12
+ STATS_DIRECTORIES = [
13
+ %w(Controllers app/controllers),
14
+ %w(Helpers app/helpers),
15
+ %w(Models app/models),
16
+ %w(Libraries lib/),
17
+ %w(APIs app/apis),
18
+ %w(Components components),
19
+ %w(Integration\ tests test/integration),
20
+ %w(Functional\ tests test/functional),
21
+ %w(Unit\ tests test/unit),
22
+ ].select { |name, dir| File.directory?(dir) }
23
+
24
+ def self.shame
25
+ stats = CodeStatistics.new(*STATS_DIRECTORIES)
26
+ code = stats.send :calculate_code
27
+ tests = stats.send :calculate_tests
28
+ msg = "Code To Test Ratio: 1:#{sprintf("%.2f", tests.to_f/code)}"
29
+ $-w = ! $-w
30
+ case @@chat_app
31
+ when :adium then
32
+ OSA.app('Adium').adium_controller.my_status_message = msg
33
+ when :ichat then
34
+ OSA.app('ichat').status_message = msg
35
+ else
36
+ raise "huh?"
37
+ end
38
+ $-w = ! $-w
39
+ $stderr.puts "Status set to: #{msg.inspect}"
40
+ end
41
+
42
+ Autotest.add_hook(:all_good) do |autotest|
43
+ shame
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ # special thanks to: Patrick Hurley <phurley@gmail.com>
2
+ # requires the ruby-snarl gem.
3
+
4
+ begin require 'rubygems'; rescue LoadError; end
5
+ require 'snarl'
6
+
7
+ module Autotest::Snarl
8
+ def self.icon
9
+ # icons from http://www.famfamfam.com/lab/icons/silk/
10
+ path = File.join(File.dirname(__FILE__), "/../icons")
11
+ {
12
+ :green => "#{path}/accept.png",
13
+ :red => "#{path}/exclamation.png",
14
+ :info => "#{path}/information.png"
15
+ }
16
+ end
17
+
18
+ def self.snarl title, msg, ico = nil
19
+ Snarl.show_message(title, msg, icon[ico])
20
+ end
21
+
22
+ Autotest.add_hook :run do |at|
23
+ snarl "Run", "Run" unless $TESTING
24
+ end
25
+
26
+ Autotest.add_hook :red do |at|
27
+ failed_tests = at.files_to_test.inject(0){ |s,a| k,v = a; s + v.size}
28
+ snarl "Tests Failed", "#{failed_tests} tests failed", :red
29
+ end
30
+
31
+ Autotest.add_hook :green do |at|
32
+ snarl "Tests Passed", "All tests passed", :green #if at.tainted
33
+ end
34
+
35
+ Autotest.add_hook :run do |at|
36
+ snarl "autotest", "autotest was started", :info unless $TESTING
37
+ end
38
+
39
+ Autotest.add_hook :interrupt do |at|
40
+ snarl "autotest", "autotest was reset", :info unless $TESTING
41
+ end
42
+
43
+ Autotest.add_hook :quit do |at|
44
+ snarl "autotest", "autotest is exiting", :info unless $TESTING
45
+ end
46
+
47
+ Autotest.add_hook :all do |at|_hook
48
+ snarl "autotest", "Tests have fully passed", :green unless $TESTING
49
+ end
50
+
51
+ end
@@ -0,0 +1,9 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::Timestamp
4
+ Autotest.add_hook :waiting do
5
+ puts
6
+ puts "# Waiting since #{Time.now.strftime "%Y-%m-%d %H:%M:%S"}"
7
+ puts
8
+ end
9
+ end
data/lib/unit_diff.rb ADDED
@@ -0,0 +1,258 @@
1
+ require 'tempfile'
2
+
3
+ ##
4
+ # UnitDiff makes reading Test::Unit output easy and fun. Instead of a
5
+ # confusing jumble of text with nearly unnoticable changes like this:
6
+ #
7
+ # 1) Failure:
8
+ # test_to_gpoints(RouteTest) [test/unit/route_test.rb:29]:
9
+ # <"new GPolyline([\n new GPoint( 47.00000, -122.00000),\n new GPoint( 46.5000
10
+ # 0, -122.50000),\n new GPoint( 46.75000, -122.75000),\n new GPoint( 46.00000,
11
+ # -123.00000)])"> expected but was
12
+ # <"new Gpolyline([\n new GPoint( 47.00000, -122.00000),\n new GPoint( 46.5000
13
+ # 0, -122.50000),\n new GPoint( 46.75000, -122.75000),\n new GPoint( 46.00000,
14
+ # -123.00000)])">.
15
+ #
16
+ #
17
+ # You get an easy-to-read diff output like this:
18
+ #
19
+ # 1) Failure:
20
+ # test_to_gpoints(RouteTest) [test/unit/route_test.rb:29]:
21
+ # 1c1
22
+ # < new GPolyline([
23
+ # ---
24
+ # > new Gpolyline([
25
+ #
26
+ # == Usage
27
+ #
28
+ # test.rb | unit_diff [options]
29
+ # options:
30
+ # -b ignore whitespace differences
31
+ # -c contextual diff
32
+ # -h show usage
33
+ # -k keep temp diff files around
34
+ # -l prefix line numbers on the diffs
35
+ # -u unified diff
36
+ # -v display version
37
+
38
+ class UnitDiff
39
+
40
+ WINDOZE = /win32/ =~ RUBY_PLATFORM unless defined? WINDOZE
41
+ DIFF = if WINDOZE
42
+ 'diff.exe'
43
+ else
44
+ if system("gdiff", __FILE__, __FILE__)
45
+ 'gdiff' # solaris and kin suck
46
+ else
47
+ 'diff'
48
+ end
49
+ end unless defined? DIFF
50
+
51
+ ##
52
+ # Handy wrapper for UnitDiff#unit_diff.
53
+
54
+ def self.unit_diff
55
+ trap 'INT' do exit 1 end
56
+ puts UnitDiff.new.unit_diff
57
+ end
58
+
59
+ def parse_input(input, output)
60
+ current = []
61
+ data = []
62
+ data << current
63
+ print_lines = true
64
+
65
+ term = "\nFinished".split(//).map { |c| c[0] }
66
+ term_length = term.size
67
+
68
+ old_sync = output.sync
69
+ output.sync = true
70
+ while line = input.gets
71
+ case line
72
+ when /^(Loaded suite|Started)/ then
73
+ print_lines = true
74
+ output.puts line
75
+ chars = []
76
+ while c = input.getc do
77
+ output.putc c
78
+ chars << c
79
+ tail = chars[-term_length..-1]
80
+ break if chars.size >= term_length and tail == term
81
+ end
82
+ output.puts input.gets # the rest of "Finished in..."
83
+ output.puts
84
+ next
85
+ when /^\s*$/, /^\(?\s*\d+\) (Failure|Error):/, /^\d+\)/ then
86
+ print_lines = false
87
+ current = []
88
+ data << current
89
+ when /^Finished in \d/ then
90
+ print_lines = false
91
+ end
92
+ output.puts line if print_lines
93
+ current << line
94
+ end
95
+ output.sync = old_sync
96
+ data = data.reject { |o| o == ["\n"] or o.empty? }
97
+ footer = data.pop
98
+
99
+ return data, footer
100
+ end
101
+
102
+ # Parses a single diff recording the header and what
103
+ # was expected, and what was actually obtained.
104
+ def parse_diff(result)
105
+ header = []
106
+ expect = []
107
+ butwas = []
108
+ footer = []
109
+ found = false
110
+ state = :header
111
+
112
+ until result.empty? do
113
+ case state
114
+ when :header then
115
+ header << result.shift
116
+ state = :expect if result.first =~ /^<|^Expected/
117
+ when :expect then
118
+ case result.first
119
+ when /^Expected (.*?) to equal (.*?):$/ then
120
+ expect << $1
121
+ butwas << $2
122
+ state = :footer
123
+ result.shift
124
+ when /^Expected (.*?), not (.*)$/m then
125
+ expect << $1
126
+ butwas << $2
127
+ state = :footer
128
+ result.shift
129
+ when /^Expected (.*?)$/ then
130
+ expect << "#{$1}\n"
131
+ result.shift
132
+ when /^to equal / then
133
+ state = :spec_butwas
134
+ bw = result.shift.sub(/^to equal (.*):?$/, '\1')
135
+ butwas << bw
136
+ else
137
+ state = :butwas if result.first.sub!(/ expected( but was|, not)/, '')
138
+ expect << result.shift
139
+ end
140
+ when :butwas then
141
+ butwas = result[0..-1]
142
+ result.clear
143
+ when :spec_butwas then
144
+ if result.first =~ /^\s+\S+ at |^:\s*$/
145
+ state = :footer
146
+ else
147
+ butwas << result.shift
148
+ end
149
+ when :footer then
150
+ butwas.last.sub!(/:$/, '')
151
+ footer = result.map {|l| l.chomp }
152
+ result.clear
153
+ else
154
+ raise "unknown state #{state}"
155
+ end
156
+ end
157
+
158
+ return header, expect, nil, footer if butwas.empty?
159
+
160
+ expect.last.chomp!
161
+ expect.first.sub!(/^<\"/, '')
162
+ expect.last.sub!(/\">$/, '')
163
+
164
+ butwas.last.chomp!
165
+ butwas.last.chop! if butwas.last =~ /\.$/
166
+ butwas.first.sub!( /^<\"/, '')
167
+ butwas.last.sub!(/\">$/, '')
168
+
169
+ return header, expect, butwas, footer
170
+ end
171
+
172
+ ##
173
+ # Scans Test::Unit output +input+ looking for comparison failures and makes
174
+ # them easily readable by passing them through diff.
175
+
176
+ def unit_diff(input=ARGF, output=$stdout)
177
+ $b = false unless defined? $b
178
+ $c = false unless defined? $c
179
+ $k = false unless defined? $k
180
+ $u = false unless defined? $u
181
+
182
+ data, footer = self.parse_input(input, output)
183
+
184
+ output = []
185
+
186
+ # Output
187
+ data.each do |result|
188
+ first = []
189
+ second = []
190
+
191
+ if result.first =~ /Error/ then
192
+ output.push result.join('')
193
+ next
194
+ end
195
+
196
+ prefix, expect, butwas, result_footer = parse_diff(result)
197
+
198
+ output.push prefix.compact.map {|line| line.strip}.join("\n")
199
+
200
+ if butwas then
201
+ output.push self.diff(expect, butwas)
202
+
203
+ output.push result_footer
204
+ output.push ''
205
+ else
206
+ output.push expect.join('')
207
+ end
208
+ end
209
+
210
+ if footer then
211
+ footer.shift if footer.first.strip.empty?# unless footer.first.nil?
212
+ output.push footer.compact.map {|line| line.strip}.join("\n")
213
+ end
214
+
215
+ return output.flatten.join("\n")
216
+ end
217
+
218
+ def diff expect, butwas
219
+ output = nil
220
+
221
+ Tempfile.open("expect") do |a|
222
+ a.write(massage(expect))
223
+ a.rewind
224
+ Tempfile.open("butwas") do |b|
225
+ b.write(massage(butwas))
226
+ b.rewind
227
+
228
+ diff_flags = $u ? "-u" : $c ? "-c" : ""
229
+ diff_flags += " -b" if $b
230
+
231
+ result = `#{DIFF} #{diff_flags} #{a.path} #{b.path}`
232
+ output = if result.empty? then
233
+ "[no difference--suspect ==]"
234
+ else
235
+ result.split(/\n/)
236
+ end
237
+
238
+ if $k then
239
+ warn "moving #{a.path} to #{a.path}.keep"
240
+ File.rename a.path, a.path + ".keep"
241
+ warn "moving #{b.path} to #{b.path}.keep"
242
+ File.rename b.path, b.path + ".keep"
243
+ end
244
+ end
245
+ end
246
+
247
+ output
248
+ end
249
+
250
+ def massage(data)
251
+ count = 0
252
+ # unescape newlines, strip <> from entire string
253
+ data = data.join
254
+ data = data.gsub(/\\n/, "\n").gsub(/0x[a-f0-9]+/m, '0xXXXXXX') + "\n"
255
+ data += "\n" unless data[-1] == ?\n
256
+ data
257
+ end
258
+ end