SlimTest 4.6.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ module Autotest::AutoUpdate
2
+ @@sleep_time, @@update_cmd, @@updater = 60, "svn up", nil
3
+
4
+ def self.sleep_time= o
5
+ @@sleep_time = o
6
+ end
7
+
8
+ def self.update_cmd= o
9
+ @@update_cmd = o
10
+ end
11
+
12
+ Autotest.add_hook :run_command do |at|
13
+ @@updater.kill if @@updater
14
+ end
15
+
16
+ Autotest.add_hook :ran_command do |at|
17
+ @@updater = Thread.start do
18
+ loop do
19
+ puts "# Waiting for #{@@sleep_time} seconds before updating"
20
+ sleep @@sleep_time
21
+ puts "# Running #{@@update_cmd}"
22
+ system @@update_cmd
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ ##
2
+ # Prefix all test runs with `bundle exec` so the runs use the bundled
3
+ # environment.
4
+
5
+ module Autotest::Bundler
6
+ Autotest.add_hook :initialize do |at|
7
+ at.prefix = "bundle exec "
8
+ false
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ ##
2
+ # Run autotest with isolate support.
3
+
4
+ module Autotest::Isolate
5
+ @@dir = "tmp/isolate/#{Gem.ruby_engine}-#{RbConfig::CONFIG['ruby_version']}"
6
+
7
+ def self.dir= o
8
+ @@dir = o
9
+ end
10
+
11
+ Autotest.add_hook :initialize do |at|
12
+ ENV["GEM_HOME"] = @@dir
13
+ ENV["GEM_PATH"] = @@dir
14
+ ENV["PATH"] += ":#{@@dir}/bin"
15
+
16
+ Gem.clear_paths
17
+ false
18
+ end
19
+ 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,56 @@
1
+ module Autotest::Preload
2
+ def self.glob
3
+ @glob
4
+ end
5
+
6
+ def self.glob= o
7
+ @glob = o
8
+ end
9
+
10
+ self.glob = "test/test_helper.rb"
11
+
12
+ Autotest.add_hook :post_initialize do |at, *args|
13
+ at.add_sigquit_handler
14
+
15
+ warn "pre-loading initializers"
16
+ t0 = Time.now
17
+ Dir[self.glob].each do |path|
18
+ require path
19
+ end
20
+ warn "done pre-loading initializers in %.2f seconds" % [Time.now - t0]
21
+
22
+ false
23
+ end
24
+ end
25
+
26
+ class Autotest
27
+ alias :old_run_tests :run_tests
28
+
29
+ def run_tests
30
+ hook :run_command
31
+
32
+ new_mtime = self.find_files_to_test
33
+ return unless new_mtime
34
+ self.last_mtime = new_mtime
35
+
36
+ begin
37
+ # TODO: deal with unit_diff and partial test runs later
38
+ original_argv = ARGV.dup
39
+ ARGV.clear
40
+
41
+ @child = fork do
42
+ trap "QUIT", "DEFAULT"
43
+ trap "INT", "DEFAULT"
44
+ files_to_test.keys.each do |file|
45
+ load file
46
+ end
47
+ end
48
+ Process.wait
49
+ ensure
50
+ @child = nil
51
+ ARGV.replace original_argv
52
+ end
53
+
54
+ hook :ran_command
55
+ end
56
+ end
@@ -0,0 +1,27 @@
1
+ module Autotest::RCov
2
+ @@command, @@options = "rcov", nil
3
+
4
+ def self.command= o
5
+ @@command = o
6
+ end
7
+
8
+ def self.pattern= o
9
+ warn "RCov.pattern= no longer has any functionality. please remove."
10
+ end
11
+
12
+ def self.options= o
13
+ @@options = o
14
+ end
15
+
16
+ Autotest.add_hook :all_good do |at|
17
+ options = @@options ? "RCOVOPTS=\"#{@@options}\"" : ""
18
+ system "rake #{@@command} #{options}"
19
+ false
20
+ end
21
+
22
+ Autotest.add_hook :initialize do |at|
23
+ at.add_exception 'coverage'
24
+ at.add_exception 'coverage.info'
25
+ false
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module Autotest::Restart
2
+ Autotest.add_hook :initialize do |at|
3
+ configs = [File.expand_path('~/.autotest'), './.autotest']
4
+ at.extra_files.concat configs
5
+ false
6
+ end
7
+
8
+ Autotest.add_hook :updated do |at, *args|
9
+ unless args.flatten.grep(/\.autotest$/).empty? then
10
+ warn "Detected change to .autotest, restarting"
11
+ at.restart
12
+ end
13
+ end
14
+ 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
@@ -0,0 +1,25 @@
1
+ class Module
2
+ def focus *wanteds
3
+ wanteds.map! { |m| m.to_s }
4
+ unwanteds = public_instance_methods(false).grep(/test_/) - wanteds
5
+ unwanteds.each do |unwanted|
6
+ remove_method unwanted
7
+ end
8
+ end
9
+
10
+ def focus_re regexp
11
+ focus(*public_instance_methods.grep(regexp))
12
+ end
13
+
14
+ def blur
15
+ parent = self.superclass
16
+
17
+ ObjectSpace.each_object Class do |klass|
18
+ next unless parent > klass
19
+ next if klass == self
20
+
21
+ klass.send :focus
22
+ klass.send :undef_method, :default_test
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,92 @@
1
+
2
+ ########################################################################
3
+ # The Idea:
4
+ #
5
+ # This is supposed to get us thinking about the various dimensions our
6
+ # testing should address. If there are states orthogonal to each other
7
+ # (eg. readable vs unreadable, logged in vs not logged in) each of
8
+ # those states should comprise a dimension in the matrix. By
9
+ # addressing it this way, we should be able to minimize the amount of
10
+ # setup/teardown code and get full coverage across our actions for all
11
+ # these edge cases and as a result have extremely clear tests.
12
+ #
13
+ ########################################################################
14
+ # Example Test Matrix Specification:
15
+ #
16
+ # matrix :example, :edge1, :edge2, :edge3, ...
17
+ # action :action1, :OK, :e_NF, :mod, ...
18
+ # action :action2, :OK, :e_RO, :na, ...
19
+ # action ...
20
+ #
21
+ ########################################################################
22
+ # Matrix:
23
+ #
24
+ # I envision the setups being a code that combines the different
25
+ # dimensions of edge case state.
26
+ #
27
+ # Something for a CMS might look like: `[df]_[ugo]_[rRwW]` where:
28
+ #
29
+ # + `[df]` for dir/file.
30
+ # + and the rest is in the style of symbolic args to chmod:
31
+ # + u/g/o = user, group, or other
32
+ # + lowercase `X` == `X`able, uppercase `X` == un`X`able, where `X`
33
+ # is read/write.
34
+ #
35
+ ########################################################################
36
+ # Action:
37
+ #
38
+ # :new/:err/:del are just examples, they should have semantic info
39
+ # attached to them.
40
+ #
41
+ # Use :na to specify an inapplicable edge case for that action.
42
+ #
43
+ # Use :OK to specify the standard positive state. It is equivalent to
44
+ # a result with the same name as the action. (eg
45
+ # matrix_test_index). This cleans up the matrix a lot and allows for
46
+ # narrower and more readable columns.
47
+ #
48
+ # Edge cases specific to an action that fall outside the matrix are
49
+ # regular tests.
50
+ #
51
+ ########################################################################
52
+ # Matrix Methods (the legos):
53
+ #
54
+ # Everything else basically equates to lego pieces:
55
+ #
56
+ # + There is one "init" method per matrix: matrix_init_#{descr}(setup_args)
57
+ # + There is one "setup" method per action: matrix_setup_#{action}(setup, expect)
58
+ # + There is one "test" method per result: matrix_test_#{result}(setup)
59
+ #
60
+ # Thus, for the matrix "example" above, the top left-most test will
61
+ # end up calling:
62
+ #
63
+ # matrix_init_example(:edge1)
64
+ # matrix_setup_action1(:edge1, :new)
65
+ # matrix_test_new(:edge1)
66
+ #
67
+ # Read the action method for exact details.
68
+ ########################################################################
69
+
70
+ module FunctionalTestMatrix
71
+ def matrix(name, *setups)
72
+ @@matrix, @@setups = name, setups
73
+ end
74
+
75
+ def action(action, *results)
76
+ testcases = @@setups.zip(results).reject { |a,b| b == :na }
77
+ testcases = Hash[*testcases.flatten]
78
+ matrix = @@matrix # bind to local scope for define_method closure
79
+
80
+ testcases.each do |setup, expected|
81
+ expected_action = expected == :OK ? action : expected
82
+ define_method "test_#{matrix}_#{action}_#{setup}" do
83
+ @action = action
84
+ send "matrix_init_#{matrix}", *setup.to_s.split(/_/).map {|c| c.intern }
85
+ send "matrix_setup_#{action}", setup, expected
86
+ send "matrix_test_#{expected_action}", setup
87
+ end
88
+ end
89
+ end
90
+
91
+ module_function :matrix, :action
92
+ end
@@ -0,0 +1,412 @@
1
+ require 'fileutils'
2
+ require 'open-uri'
3
+
4
+ ##
5
+ # multiruby_setup is a script to help you manage multiruby.
6
+ #
7
+ # usage: multiruby_setup [-h|cmd|spec...]
8
+ #
9
+ # cmds:
10
+ #
11
+ # -h, --help, help = show this help.
12
+ # build = build and install everything. used internally.
13
+ # clean = clean scm build dirs and remove non-scm build dirs.
14
+ # list = print installed versions.
15
+ # rm:$version = remove a particular version.
16
+ # rubygems:merge = symlink all rubygem dirs to one dir.
17
+ # tags = list all tags from svn.
18
+ # update = update svn builds.
19
+ # update:rubygems = update rubygems and nuke install dirs.
20
+ #
21
+ # specs:
22
+ #
23
+ # the_usual = alias for latest versions from tar + rubygems
24
+ # mri:svn:current = alias for mri:svn:releases and mri:svn:branches.
25
+ # mri:svn:releases = alias for supported releases of mri ruby.
26
+ # mri:svn:branches = alias for active branches of mri ruby.
27
+ # mri:svn:branch:$branch = install a specific $branch of mri from svn.
28
+ # mri:svn:tag:$tag = install a specific $tag of mri from svn.
29
+ # mri:tar:$version = install a specific $version of mri from tarball.
30
+ #
31
+ # environment variables:
32
+ #
33
+ # GEM_URL = url for rubygems tarballs
34
+ # MRI_SVN = url for MRI SVN
35
+ # RUBY_URL = url for MRI tarballs
36
+ # VERSIONS = what versions to install
37
+ #
38
+ # RUBYOPT is cleared on installs.
39
+ #
40
+ # NOTES:
41
+ #
42
+ # * you can add a symlink to your rubinius build into ~/.multiruby/install
43
+ # * I need patches/maintainers for other implementations.
44
+ #
45
+ module Multiruby
46
+ def self.env name, fallback; ENV[name] || fallback; end # :nodoc:
47
+
48
+ TAGS = %w( 1_8_7 1_9_1 1_9_2)
49
+ BRANCHES = %w(1_8 1_8_7 1_9 trunk)
50
+
51
+ VERSIONS = env('VERSIONS', TAGS.join(":").gsub(/_/, '.')).split(/:/)
52
+ MRI_SVN = env 'MRI_SVN', 'http://svn.ruby-lang.org/repos/ruby'
53
+ RUBY_URL = env 'RUBY_URL', 'http://ftp.ruby-lang.org/pub/ruby'
54
+ GEM_URL = env 'GEM_URL', 'http://files.rubyforge.vm.bytemark.co.uk/rubygems'
55
+
56
+ HELP = []
57
+
58
+ File.readlines(__FILE__).each do |line|
59
+ next unless line =~ /^#( |$)/
60
+ HELP << line.sub(/^# ?/, '')
61
+ end
62
+
63
+ def self.build_and_install
64
+ ENV.delete 'RUBYOPT'
65
+
66
+ root_dir = self.root_dir
67
+ versions = []
68
+
69
+ Dir.chdir root_dir do
70
+ self.setup_dirs
71
+
72
+ rubygems = Dir["versions/rubygems*.tgz"]
73
+ abort "You should delete all but one rubygem tarball" if rubygems.size > 1
74
+ rubygem_tarball = File.expand_path rubygems.last rescue nil
75
+
76
+ Dir.chdir "build" do
77
+ Dir["../versions/*"].sort.each do |tarball|
78
+ next if tarball =~ /rubygems/
79
+
80
+ build_dir = File.basename tarball, ".tar.gz"
81
+ version = build_dir.sub(/^ruby-?/, '')
82
+ versions << version
83
+ inst_dir = "#{root_dir}/install/#{version}"
84
+
85
+ unless test ?d, inst_dir then
86
+ unless test ?d, build_dir then
87
+ if test ?d, tarball then
88
+ dir = File.basename tarball
89
+ FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
90
+ else
91
+ puts "creating #{inst_dir}"
92
+ Dir.mkdir inst_dir
93
+ run "tar zxf #{tarball}"
94
+ end
95
+ end
96
+ Dir.chdir build_dir do
97
+ puts "building and installing #{version}"
98
+ if test ?f, "configure.in" then
99
+ gnu_utils_build inst_dir
100
+ elsif test ?f, "Rakefile" then
101
+ rake_build inst_dir
102
+ else
103
+ raise "dunno how to build"
104
+ end
105
+
106
+ if rubygem_tarball and version !~ /1[._-]9|mri_trunk|rubinius/ then
107
+ rubygems = File.basename rubygem_tarball, ".tgz"
108
+ run "tar zxf #{rubygem_tarball}" unless test ?d, rubygems
109
+
110
+ Dir.chdir rubygems do
111
+ run "../ruby ./setup.rb --no-rdoc --no-ri", "../log.rubygems"
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ versions
121
+ end
122
+
123
+ def self.clean
124
+ self.each_scm_build_dir do |style|
125
+ case style
126
+ when :svn then
127
+ if File.exist? "Rakefile" then
128
+ run "rake clean"
129
+ elsif File.exist? "Makefile" then
130
+ run "make clean"
131
+ end
132
+ else
133
+ FileUtils.rm_rf Dir.pwd
134
+ end
135
+ end
136
+ end
137
+
138
+ def self.each_scm_build_dir
139
+ Multiruby.in_build_dir do
140
+ Dir["*"].each do |dir|
141
+ next unless File.directory? dir
142
+ Dir.chdir dir do
143
+ if File.exist?(".svn") then
144
+ yield :svn
145
+ else
146
+ yield :none
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ def self.matching_versions url, matching=nil
154
+ file = URI.parse(url).read
155
+
156
+ map = {
157
+ "preview" => "beta",
158
+ "rc" => "beta2",
159
+ "p" => "release",
160
+ "tar" => "aargh",
161
+ "gz" => "aargh",
162
+ }
163
+
164
+ versions = file.scan(/href="(ruby.*tar.gz)"/).flatten.sort_by { |s|
165
+ s.scan(/\d+|[a-z]+/).map { |a| Integer(a) rescue map[a] || a }
166
+ }
167
+
168
+ versions = versions.grep(/#{Regexp.escape(matching)}/) if matching
169
+
170
+ versions
171
+ end
172
+
173
+ def self.fetch_tar v
174
+ in_versions_dir do
175
+ warn " Determining latest version for #{v}"
176
+ ver = v[/\d+\.\d+/]
177
+ base = matching_versions("#{RUBY_URL}/#{ver}/", v).last
178
+ abort "Could not determine release for #{v}" unless base
179
+ url = File.join RUBY_URL, ver, base
180
+ unless File.file? base then
181
+ warn " Fetching #{base} via HTTP... this might take a while."
182
+ open(url) do |f|
183
+ File.open base, 'w' do |out|
184
+ out.write f.read
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ def self.gnu_utils_build inst_dir
192
+ run "autoconf" unless test ?f, "configure"
193
+ run "./configure --enable-shared --prefix #{inst_dir}", "log.configure" unless
194
+ test ?f, "Makefile"
195
+ run "(nice make -j4; nice make)", "log.build"
196
+ run "make install", "log.install"
197
+ end
198
+
199
+ def self.help
200
+ puts HELP.join
201
+ end
202
+
203
+ def self.in_build_dir
204
+ in_root_dir "build" do
205
+ yield
206
+ end
207
+ end
208
+
209
+ def self.in_install_dir
210
+ in_root_dir "install" do
211
+ yield
212
+ end
213
+ end
214
+
215
+ def self.in_root_dir subdir = ""
216
+ Dir.chdir File.join(self.root_dir, subdir) do
217
+ yield
218
+ end
219
+ end
220
+
221
+ def self.in_tmp_dir
222
+ in_root_dir "tmp" do
223
+ yield
224
+ end
225
+ end
226
+
227
+ def self.in_versions_dir
228
+ in_root_dir "versions" do
229
+ yield
230
+ end
231
+ end
232
+
233
+ def self.list
234
+ puts "Known versions:"
235
+ in_install_dir do
236
+ Dir["*"].sort.each do |d|
237
+ puts " #{d}"
238
+ end
239
+ end
240
+ end
241
+
242
+ def self.merge_rubygems
243
+ in_install_dir do
244
+ gems = Dir["*/lib/ruby/gems"]
245
+
246
+ unless test ?d, "../gems" then
247
+ FileUtils.mv gems.first, ".."
248
+ end
249
+
250
+ gems.each do |d|
251
+ FileUtils.rm_rf d
252
+ FileUtils.ln_sf "../../../../gems", d
253
+ end
254
+ end
255
+ end
256
+
257
+ def self.mri_latest_tag v
258
+ Multiruby.tags.grep(/#{v}/).last
259
+ end
260
+
261
+ def self.rake_build inst_dir
262
+ run "rake", "log.build"
263
+ FileUtils.ln_sf "../build/#{File.basename Dir.pwd}", inst_dir
264
+ end
265
+
266
+ def self.rm name
267
+ Multiruby.in_root_dir do
268
+ FileUtils.rm_rf Dir["*/#{name}"]
269
+ f = "versions/ruby-#{name}.tar.gz"
270
+ File.unlink f if test ?f, f
271
+ end
272
+ end
273
+
274
+ def self.root_dir
275
+ root_dir = File.expand_path(ENV['MULTIRUBY'] ||
276
+ File.join(ENV['HOME'], ".multiruby"))
277
+
278
+ unless test ?d, root_dir then
279
+ puts "creating #{root_dir}"
280
+ Dir.mkdir root_dir, 0700
281
+ end
282
+
283
+ root_dir
284
+ end
285
+
286
+ def self.run base_cmd, log = nil
287
+ cmd = base_cmd
288
+ cmd += " > #{log} 2>&1" if log
289
+ puts "Running command: #{cmd}"
290
+ raise "ERROR: Command failed with exit code #{$?}" unless system cmd
291
+ end
292
+
293
+ def self.setup_dirs download = true
294
+ %w(build install versions tmp).each do |dir|
295
+ unless test ?d, dir then
296
+ puts "creating #{dir}"
297
+ Dir.mkdir dir
298
+ if dir == "versions" && download then
299
+ warn " Downloading initial ruby tarballs to ~/.multiruby/versions:"
300
+ VERSIONS.each do |v|
301
+ self.fetch_tar v
302
+ end
303
+ warn " ...done"
304
+ warn " Put other ruby tarballs in ~/.multiruby/versions to use them."
305
+ end
306
+ end
307
+ end
308
+ end
309
+
310
+ def self.svn_co url, dir
311
+ Multiruby.in_versions_dir do
312
+ Multiruby.run "svn co #{url} #{dir}" unless File.directory? dir
313
+ FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
314
+ end
315
+ end
316
+
317
+ def self.tags
318
+ tags = nil
319
+ Multiruby.in_tmp_dir do
320
+ cache = "svn.tag.cache"
321
+ File.unlink cache if Time.now - File.mtime(cache) > 3600 rescue nil
322
+
323
+ File.open cache, "w" do |f|
324
+ f.write `svn ls #{MRI_SVN}/tags/`
325
+ end unless File.exist? cache
326
+
327
+ tags = File.read(cache).split(/\n/).grep(/^v/).reject {|s| s =~ /preview/}
328
+ end
329
+
330
+ tags = tags.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }
331
+ end
332
+
333
+ def self.update
334
+ # TODO:
335
+ # update will look at the dir name and act accordingly rel_.* will
336
+ # figure out latest tag on that name and svn sw to it trunk and
337
+ # others will just svn update
338
+
339
+ clean = []
340
+
341
+ self.each_scm_build_dir do |style|
342
+ dir = File.basename(Dir.pwd)
343
+ warn dir
344
+
345
+ case style
346
+ when :svn then
347
+ case dir
348
+ when /mri_\d/ then
349
+ system "svn cleanup" # just in case
350
+ svn_up = `svn up`
351
+ in_build_dir do
352
+ if svn_up =~ /^[ADUCG] / then
353
+ clean << dir
354
+ else
355
+ warn " no update"
356
+ end
357
+ FileUtils.ln_sf "../build/#{dir}", "../versions/#{dir}"
358
+ end
359
+ when /mri_rel_(.+)/ then
360
+ ver = $1
361
+ url = `svn info`[/^URL: (.*)/, 1]
362
+ latest = self.mri_latest_tag(ver).chomp('/')
363
+ new_url = File.join(File.dirname(url), latest)
364
+ if new_url != url then
365
+ run "svn sw #{new_url}"
366
+ clean << dir
367
+ else
368
+ warn " no update"
369
+ end
370
+ else
371
+ warn " update in this svn dir not supported yet: #{dir}"
372
+ end
373
+ else
374
+ warn " update in non-svn dir not supported yet: #{dir}"
375
+ end
376
+ end
377
+
378
+ in_install_dir do
379
+ clean.each do |dir|
380
+ warn "removing install/#{dir}"
381
+ FileUtils.rm_rf dir
382
+ end
383
+ end
384
+ end
385
+
386
+ def self.update_rubygems
387
+ warn " Determining latest version for rubygems"
388
+ html = URI.parse(GEM_URL).read
389
+
390
+ versions = html.scan(/href="rubygems-update-(\d+(?:\.\d+)+).gem/i).flatten
391
+ latest = versions.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }.last
392
+
393
+ Multiruby.in_versions_dir do
394
+ file = "rubygems-#{latest}.tgz"
395
+ unless File.file? file then
396
+ warn " Fetching rubygems-#{latest}.tgz via HTTP."
397
+ File.unlink(*Dir["rubygems*"])
398
+ File.open file, 'w' do |f|
399
+ f.write URI.parse(GEM_URL+"/"+file).read
400
+ end
401
+ end
402
+ end
403
+
404
+ Multiruby.in_build_dir do
405
+ FileUtils.rm_rf Dir["rubygems*"]
406
+ end
407
+
408
+ Multiruby.in_install_dir do
409
+ FileUtils.rm_rf Dir["*"]
410
+ end
411
+ end
412
+ end