SlimTest 4.6.1.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.
@@ -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