ratch 0.2.2 → 0.2.3
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/COPYING +674 -0
- data/README +5 -5
- data/bin/lt +11 -11
- data/bin/ratch +3 -2
- data/demo/README +1 -0
- data/demo/WILMA +1 -0
- data/demo/doc/rdoc/created.rid +1 -1
- data/demo/doc/rdoc/files/README.html +1 -1
- data/demo/doc/rdoc/files/lib/foo/foo_rb.html +1 -1
- data/demo/doc/rdoc/index.html +3 -3
- data/demo/p.rb +9 -0
- data/demo/r.rb +6 -0
- data/demo/t.rb +3 -0
- data/demo/task/config.yaml +2 -0
- data/demo/{util → task}/one +0 -0
- data/demo/task/rdoc +88 -0
- data/demo/task/rdoc-old +182 -0
- data/demo/task/simplebuild +15 -0
- data/demo/task/stats +6 -0
- data/demo/task/task +6 -0
- data/demo/{util → task}/tryme +0 -0
- data/lib/ratch/argvutils.rb +57 -14
- data/lib/ratch/batch.rb +73 -21
- data/lib/ratch/batchable.rb +56 -26
- data/lib/ratch/batchfile.rb +95 -0
- data/lib/ratch/buildable.rb +117 -42
- data/lib/ratch/configutils.rb +43 -13
- data/lib/ratch/consoleutils.rb +76 -19
- data/lib/ratch/emailutils.rb +24 -0
- data/lib/ratch/facets/multiglob.rb +160 -0
- data/lib/ratch/fileutils.rb +40 -8
- data/lib/ratch/options.rb +43 -4
- data/lib/ratch/taskable.rb +48 -12
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/announce +0 -0
- data/lib/ratch/toolset/ruby/crosstest +305 -0
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/extest +0 -0
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/install +0 -0
- data/lib/ratch/toolset/ruby/isotest +293 -0
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/load +0 -0
- data/lib/ratch/toolset/ruby/loadtest +28 -0
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/notes +0 -0
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/publish +0 -0
- data/lib/ratch/toolset/ruby/rdoc +88 -0
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/setup +0 -0
- data/{data/ratch/rubyproject → lib/ratch/toolset/ruby}/stats +0 -0
- data/lib/ratch/toolset/ruby/syntax +29 -0
- data/lib/ratch/toolset/ruby/test +26 -0
- data/lib/ratch/uploadutils.rb +25 -4
- data/log/history.rd +10 -0
- data/log/recent.rd +8 -0
- data/log/todo.rd +2 -0
- data/man/ratch.man +73 -0
- data/meta/MANIFEST +45 -31
- data/meta/{RATCH-0.2.2.roll → ratch-0.2.3.roll} +3 -3
- data/task/clobber/package +10 -0
- data/task/config.yaml +4 -0
- data/task/man +14 -0
- data/task/publish +1 -1
- data/task/rdoc +6 -0
- metadata +64 -40
- data/LICENSE +0 -344
- data/data/ratch/rubyproject/rdoc +0 -42
- data/demo/util/conf/rdoc +0 -4
- data/demo/util/rdoc +0 -39
- data/dev/install +0 -89
- data/dev/install.0 +0 -49
- data/dev/install.1 +0 -63
- data/dev/ludo +0 -25
- data/dev/oldtaskable.rb +0 -573
- data/dev/taskable-simple.rb +0 -42
- data/dev/taskable.rb +0 -120
- data/lib/ratch/t.rb +0 -0
- data/lib/ratch/taskutils.rb +0 -41
@@ -0,0 +1,160 @@
|
|
1
|
+
# TITLE:
|
2
|
+
#
|
3
|
+
# Multiglob
|
4
|
+
#
|
5
|
+
# SUMMARY:
|
6
|
+
#
|
7
|
+
# Dir extensions for globbing multiple locations at once.
|
8
|
+
#
|
9
|
+
# COPYING:
|
10
|
+
#
|
11
|
+
# Copyright (c) 2007 Psi T Corp.
|
12
|
+
#
|
13
|
+
# This file is part of the ProUtils' Ratch program.
|
14
|
+
#
|
15
|
+
# Ratch is free software: you can redistribute it and/or modify
|
16
|
+
# it under the terms of the GNU General Public License as published by
|
17
|
+
# the Free Software Foundation, either version 3 of the License, or
|
18
|
+
# (at your option) any later version.
|
19
|
+
#
|
20
|
+
# Ratch is distributed in the hope that it will be useful,
|
21
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
22
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
23
|
+
# GNU General Public License for more details.
|
24
|
+
#
|
25
|
+
# You should have received a copy of the GNU General Public License
|
26
|
+
# along with Ratch. If not, see <http://www.gnu.org/licenses/>.
|
27
|
+
|
28
|
+
#
|
29
|
+
class Dir
|
30
|
+
|
31
|
+
# Like +glob+ but can take multiple patterns.
|
32
|
+
#
|
33
|
+
# Dir.multiglob( '*.rb', '*.py' )
|
34
|
+
#
|
35
|
+
# Rather then constants for options multiglob accepts a trailing options
|
36
|
+
# hash of symbol keys.
|
37
|
+
#
|
38
|
+
# :noescape File::FNM_NOESCAPE
|
39
|
+
# :casefold File::FNM_CASEFOLD
|
40
|
+
# :pathname File::FNM_PATHNAME
|
41
|
+
# :dotmatch File::FNM_DOTMATCH
|
42
|
+
# :strict File::FNM_PATHNAME && File::FNM_DOTMATCH
|
43
|
+
#
|
44
|
+
# It also has an option for recurse.
|
45
|
+
#
|
46
|
+
# :recurse Recurively include contents of directories.
|
47
|
+
#
|
48
|
+
# For example
|
49
|
+
#
|
50
|
+
# Dir.multiglob( '*', :recurse => true )
|
51
|
+
#
|
52
|
+
# would have the same result as
|
53
|
+
#
|
54
|
+
# Dir.multiglob('**/*')
|
55
|
+
#
|
56
|
+
# Multiglob also accepts '+' and '-' prefixes. Any entry that begins with a '-'
|
57
|
+
# is treated as an exclusion glob and will be removed from the final result.
|
58
|
+
# For example, to collect all files in the current directory, less ruby scripts:
|
59
|
+
#
|
60
|
+
# Dir.multiglob( '*', '-*.rb' )
|
61
|
+
#
|
62
|
+
# This is very useful in collecting files as specificed by a configuration
|
63
|
+
# parameter.
|
64
|
+
|
65
|
+
def self.multiglob( *patterns )
|
66
|
+
options = (Hash === patterns.last ? patterns.pop : {})
|
67
|
+
|
68
|
+
bitflags = 0
|
69
|
+
bitflags |= File::FNM_NOESCAPE if options[:noescape]
|
70
|
+
bitflags |= File::FNM_CASEFOLD if options[:casefold]
|
71
|
+
bitflags |= File::FNM_PATHNAME if options[:pathname] or options[:strict]
|
72
|
+
bitflags |= File::FNM_DOTMATCH if options[:dotmatch] or options[:strict]
|
73
|
+
|
74
|
+
patterns = [patterns].flatten.compact
|
75
|
+
|
76
|
+
patterns_include = patterns.select{ |f| f !~ /^[-]/ }
|
77
|
+
patterns_exclude = patterns.select{ |f| f =~ /^[-]/ }
|
78
|
+
|
79
|
+
patterns_include.collect!{ |f| f =~ /^[+]/ ? f[1..-1] : f }
|
80
|
+
patterns_exclude.collect!{ |f| f =~ /^[-]/ ? f[1..-1] : f }
|
81
|
+
|
82
|
+
if options[:recurse]
|
83
|
+
patterns_include += patterns_include.collect{ |f| File.join(f, '**', '*') }
|
84
|
+
patterns_exclude += patterns_exclude.collect{ |f| File.join(f, '**', '*') }
|
85
|
+
end
|
86
|
+
|
87
|
+
files = []
|
88
|
+
files += patterns_include.collect{ |pattern| Dir.glob(pattern, bitflags) }.flatten.uniq
|
89
|
+
files -= patterns_exclude.collect{ |pattern| Dir.glob(pattern, bitflags) }.flatten.uniq
|
90
|
+
|
91
|
+
return files
|
92
|
+
end
|
93
|
+
|
94
|
+
# The same as +multiglob+, but recusively includes directories.
|
95
|
+
#
|
96
|
+
# Dir.multiglob_r( 'folder' )
|
97
|
+
#
|
98
|
+
# is equivalent to
|
99
|
+
#
|
100
|
+
# Dir.multiglob( 'folder', :recurse=>true )
|
101
|
+
#
|
102
|
+
# The effect of which is
|
103
|
+
#
|
104
|
+
# Dir.multiglob( 'folder', 'folder/**/*' )
|
105
|
+
|
106
|
+
def self.multiglob_r( *patterns )
|
107
|
+
options = (Hash === patterns.last ? patterns.pop : {})
|
108
|
+
options[:recurse] = true
|
109
|
+
patterns << options
|
110
|
+
multiglob(*patterns)
|
111
|
+
end
|
112
|
+
|
113
|
+
# This is just like multiglob but handles a base pattern such that
|
114
|
+
# if the +patterns+ list starts with a '+' or '-' entry, then the base
|
115
|
+
# will be included in the result, otherwise it will be omitted.
|
116
|
+
#
|
117
|
+
# Dir.multiglob_with_default('*.yaml', '-*.rb') #=> [ 'foo.yaml' ]
|
118
|
+
# Dir.multiglob_with_default('*.yaml', '+*.rb') #=> [ 'foo.yaml', 'foo.rb' ]
|
119
|
+
# Dir.multiglob_with_default('*.yaml', '*.rb') #=> [ 'foo.rb' ]
|
120
|
+
#
|
121
|
+
# This is useful when a configuration option needs to supply a file list
|
122
|
+
# that may include files, exclude files or append files to a default list.
|
123
|
+
#
|
124
|
+
# TODO Deprecate this and replace with :default option on regular multiglob.
|
125
|
+
|
126
|
+
def self.multiglob_with_default(default, *patterns)
|
127
|
+
default = [default].flatten.compact
|
128
|
+
patterns = patterns.flatten.compact
|
129
|
+
|
130
|
+
if patterns.empty?
|
131
|
+
patterns = default
|
132
|
+
elsif patterns.first =~ /^[+-]/
|
133
|
+
patterns = default + patterns
|
134
|
+
end
|
135
|
+
|
136
|
+
multiglob(*patterns)
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
# _____ _
|
144
|
+
# |_ _|__ ___| |_
|
145
|
+
# | |/ _ \/ __| __|
|
146
|
+
# | | __/\__ \ |_
|
147
|
+
# |_|\___||___/\__|
|
148
|
+
#
|
149
|
+
|
150
|
+
# TODO Need to mock file system.
|
151
|
+
|
152
|
+
=begin #no test yet
|
153
|
+
|
154
|
+
require 'test/unit'
|
155
|
+
|
156
|
+
class TestDir < Test::Unit::TestCase
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
=end
|
data/lib/ratch/fileutils.rb
CHANGED
@@ -1,4 +1,28 @@
|
|
1
|
+
# TITLE:
|
2
|
+
#
|
3
|
+
# FileUtils
|
4
|
+
#
|
5
|
+
# COPYING:
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Psi T Corp.
|
8
|
+
#
|
9
|
+
# This file is part of the ProUtils' Ratch program.
|
10
|
+
#
|
11
|
+
# Ratch is free software: you can redistribute it and/or modify
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
13
|
+
# the Free Software Foundation, either version 3 of the License, or
|
14
|
+
# (at your option) any later version.
|
15
|
+
#
|
16
|
+
# Ratch is distributed in the hope that it will be useful,
|
17
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
# GNU General Public License for more details.
|
20
|
+
#
|
21
|
+
# You should have received a copy of the GNU General Public License
|
22
|
+
# along with Ratch. If not, see <http://www.gnu.org/licenses/>.
|
23
|
+
|
1
24
|
require 'fileutils'
|
25
|
+
require 'ratch/facets/multiglob'
|
2
26
|
|
3
27
|
|
4
28
|
module Ratch
|
@@ -11,6 +35,14 @@ module Ratch
|
|
11
35
|
Dir.glob(*args, &blk)
|
12
36
|
end
|
13
37
|
|
38
|
+
def multiglob(*args, &blk)
|
39
|
+
Dir.multiglob(*args, &blk)
|
40
|
+
end
|
41
|
+
|
42
|
+
def multiglob_r(*args, &blk)
|
43
|
+
Dir.multiglob_r(*args, &blk)
|
44
|
+
end
|
45
|
+
|
14
46
|
# Read file.
|
15
47
|
|
16
48
|
def file_read(path)
|
@@ -130,13 +162,13 @@ module Ratch
|
|
130
162
|
alias_method :exist!, :exists! ; module_function :exist!
|
131
163
|
alias_method :path!, :exists! ; module_function :path!
|
132
164
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
165
|
+
# # Is a file a task?
|
166
|
+
#
|
167
|
+
# def task?(path)
|
168
|
+
# task = File.dirname($0) + "/#{path}"
|
169
|
+
# task.chomp!('!')
|
170
|
+
# task if FileTest.file?(task) && FileTest.executable?(task)
|
171
|
+
# end
|
140
172
|
|
141
173
|
# Is a file a command executable?
|
142
174
|
#
|
@@ -152,7 +184,7 @@ module Ratch
|
|
152
184
|
# This is a support method of #bin?
|
153
185
|
|
154
186
|
def command_paths
|
155
|
-
@command_paths ||= ENV['PATH'].split(
|
187
|
+
@command_paths ||= ENV['PATH'].split(/[:;]/)
|
156
188
|
end
|
157
189
|
|
158
190
|
# TODO Make more robust.
|
data/lib/ratch/options.rb
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# TITLE:
|
2
|
+
#
|
3
|
+
# GeneralOptions
|
4
|
+
#
|
5
|
+
# COPYING:
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Psi T Corp.
|
8
|
+
#
|
9
|
+
# This file is part of the ProUtils' Ratch program.
|
10
|
+
#
|
11
|
+
# Ratch is free software: you can redistribute it and/or modify
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
13
|
+
# the Free Software Foundation, either version 3 of the License, or
|
14
|
+
# (at your option) any later version.
|
15
|
+
#
|
16
|
+
# Ratch is distributed in the hope that it will be useful,
|
17
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
# GNU General Public License for more details.
|
20
|
+
#
|
21
|
+
# You should have received a copy of the GNU General Public License
|
22
|
+
# along with Ratch. If not, see <http://www.gnu.org/licenses/>.
|
1
23
|
|
2
24
|
module Ratch
|
3
25
|
|
@@ -22,7 +44,19 @@ module Ratch
|
|
22
44
|
# Debug mode.
|
23
45
|
|
24
46
|
def debug?
|
25
|
-
@debug
|
47
|
+
@debug ||= %w{--debug}.any?{|a| argv.delete(a)}
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
|
52
|
+
def verbose?
|
53
|
+
@verbose ||= %w{--verbose}.any?{|a| argv.delete(a)}
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
|
58
|
+
def verbose!
|
59
|
+
@verbose = true
|
26
60
|
end
|
27
61
|
|
28
62
|
#
|
@@ -42,16 +76,21 @@ module Ratch
|
|
42
76
|
def noharm?
|
43
77
|
@noharm ||= %w{--dryrun --dry-run --noharm}.any?{|a| argv.delete(a)}
|
44
78
|
end
|
45
|
-
|
46
79
|
alias_method :dryrun?, :noharm? ; module_function :dryrun?
|
47
80
|
|
48
|
-
#
|
49
|
-
|
50
81
|
def noharm!
|
51
82
|
@noharm = true
|
52
83
|
end
|
53
84
|
alias_method :dryrun!, :noharm! ; module_function :dryrun!
|
54
85
|
|
86
|
+
# Force mode.
|
87
|
+
|
88
|
+
def force?
|
89
|
+
@force ||= %w{--force}.any?{|a| argv.delete(a)}
|
90
|
+
end
|
91
|
+
|
92
|
+
def force! ; @force = true ; end
|
93
|
+
|
55
94
|
end
|
56
95
|
|
57
96
|
end
|
data/lib/ratch/taskable.rb
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
# TITLE:
|
2
|
+
#
|
3
|
+
# Taskable
|
4
|
+
#
|
5
|
+
# COPYING:
|
6
|
+
#
|
7
|
+
# Copyright (c) 2007 Psi T Corp.
|
8
|
+
#
|
9
|
+
# This file is part of the ProUtils' Ratch program.
|
10
|
+
#
|
11
|
+
# Ratch is free software: you can redistribute it and/or modify
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
13
|
+
# the Free Software Foundation, either version 3 of the License, or
|
14
|
+
# (at your option) any later version.
|
15
|
+
#
|
16
|
+
# Ratch is distributed in the hope that it will be useful,
|
17
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
# GNU General Public License for more details.
|
20
|
+
#
|
21
|
+
# You should have received a copy of the GNU General Public License
|
22
|
+
# along with Ratch. If not, see <http://www.gnu.org/licenses/>.
|
23
|
+
|
1
24
|
module Ratch
|
2
25
|
|
3
26
|
# = Taskable Mixin
|
@@ -6,7 +29,7 @@ module Ratch
|
|
6
29
|
|
7
30
|
# Reference task manager.
|
8
31
|
def task_manager
|
9
|
-
@task_manager ||= TaskManager.new
|
32
|
+
@task_manager ||= TaskManager.new(self)
|
10
33
|
end
|
11
34
|
|
12
35
|
# Define a main task.
|
@@ -46,8 +69,10 @@ module Ratch
|
|
46
69
|
class TaskManager
|
47
70
|
attr :main
|
48
71
|
attr :tasks
|
72
|
+
attr :runspace
|
49
73
|
|
50
|
-
def initialize
|
74
|
+
def initialize(runspace)
|
75
|
+
@runspace = runspace
|
51
76
|
@main = nil
|
52
77
|
@tasks = {}
|
53
78
|
end
|
@@ -78,14 +103,25 @@ module Ratch
|
|
78
103
|
if list.include?(name)
|
79
104
|
raise "Circular dependency #{name}."
|
80
105
|
end
|
81
|
-
task = @tasks[name]
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
106
|
+
if task = @tasks[name]
|
107
|
+
task.needs.each do |need|
|
108
|
+
need = need.to_s
|
109
|
+
next if list.include?(need)
|
110
|
+
#@tasks[need].plan(need, list)
|
111
|
+
plan(need, list)
|
112
|
+
end
|
113
|
+
list << task.name
|
114
|
+
else
|
115
|
+
if fname = runspace.batch?(name) # TODO THIS TIES TASKS INTO BATCH, BETTER WAY?
|
116
|
+
task = Task.new(name) do
|
117
|
+
runspace.batch(fname)
|
118
|
+
end
|
119
|
+
@tasks[name] = task
|
120
|
+
list << task.name
|
121
|
+
else
|
122
|
+
abort "no task -- #{name}"
|
123
|
+
end
|
87
124
|
end
|
88
|
-
list << task.name
|
89
125
|
return list
|
90
126
|
end
|
91
127
|
|
@@ -96,13 +132,13 @@ module Ratch
|
|
96
132
|
class Task
|
97
133
|
|
98
134
|
attr :name
|
99
|
-
attr :
|
135
|
+
attr :needs
|
100
136
|
attr :action
|
101
137
|
|
102
138
|
#
|
103
|
-
def initialize(name, *
|
139
|
+
def initialize(name, *needs, &action)
|
104
140
|
@name = name.to_s
|
105
|
-
@
|
141
|
+
@needs = needs
|
106
142
|
@action = action
|
107
143
|
end
|
108
144
|
|
File without changes
|
@@ -0,0 +1,305 @@
|
|
1
|
+
#!/usr/bin/env ratch
|
2
|
+
|
3
|
+
# run cross comparison tests
|
4
|
+
#
|
5
|
+
# This tool runs unit tests in pairs to make
|
6
|
+
# sure there is cross library compatibility.
|
7
|
+
|
8
|
+
require 'facets/hash/rekey'
|
9
|
+
require 'facets/string/tabs'
|
10
|
+
require 'facets/progressbar'
|
11
|
+
|
12
|
+
require 'test/unit/ui/testrunnermediator' #require 'test/unit'
|
13
|
+
::Test::Unit.run = true # Don't autorun tests!
|
14
|
+
|
15
|
+
|
16
|
+
main :crosstest do
|
17
|
+
run_crosstests
|
18
|
+
end
|
19
|
+
|
20
|
+
# Run unit-tests. Each test is run in a separate interpretor
|
21
|
+
# to prevent script clash. This makes for a more robust test
|
22
|
+
# facility and prevents potential conflicts between test scripts.
|
23
|
+
#
|
24
|
+
# tests Test files (eg. test/tc_**/*.rb) [test/**/*]
|
25
|
+
# libs Directories to include in load path.
|
26
|
+
# ('./lib' is always included)
|
27
|
+
# live Deactive use of local libs and test against install.
|
28
|
+
# reqs List of files to require prior to running tests.
|
29
|
+
# extract Extract embedded tests first? [false]
|
30
|
+
#
|
31
|
+
# To isolate tests this tool marshals test results across a
|
32
|
+
# stdout->stdin shell pipe. This prevents interfence of one
|
33
|
+
# script's tests on another. But consequently it is not always
|
34
|
+
# possible to send debug info to stdout in the tests themselves
|
35
|
+
# (eg. #p and #puts).
|
36
|
+
|
37
|
+
def run_crosstests
|
38
|
+
info = configuration['test']
|
39
|
+
|
40
|
+
tests = info['files'] || 'test/unit/**/test_*.rb'
|
41
|
+
libs = info['libpath']
|
42
|
+
reqs = info['require']
|
43
|
+
live = info['live']
|
44
|
+
#extract = info['extract']
|
45
|
+
|
46
|
+
tests = [ tests ].flatten
|
47
|
+
libs = [ libs ].flatten
|
48
|
+
|
49
|
+
results = TestResults.new #(style)
|
50
|
+
|
51
|
+
# get test files
|
52
|
+
test_libs = libs.join(':')
|
53
|
+
test_files = Dir.multiglob( *tests )
|
54
|
+
if test_files.empty?
|
55
|
+
puts "Tests [NONE]"
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
# run tests
|
60
|
+
|
61
|
+
if trace?
|
62
|
+
pbar = nil
|
63
|
+
size = test_files.collect{|f| f.size}.max * 2 + 5
|
64
|
+
dots = '.' * size
|
65
|
+
else
|
66
|
+
pbar = Console::ProgressBar.new('Testing', test_files.size ** 2)
|
67
|
+
pbar.inc
|
68
|
+
end
|
69
|
+
|
70
|
+
test_files.each do |test_file|
|
71
|
+
next unless File.file?(test_file)
|
72
|
+
|
73
|
+
test_files.each do |test_file_x|
|
74
|
+
next unless File.file?(test_file_x)
|
75
|
+
next if test_file == test_file_x
|
76
|
+
|
77
|
+
pbar.inc if pbar
|
78
|
+
unless pbar
|
79
|
+
out = test_file +' : ' + test_file_x
|
80
|
+
print out + dots[out.size..-1]
|
81
|
+
$stdout.flush
|
82
|
+
end
|
83
|
+
|
84
|
+
r = fork_test( test_file, test_file_x, :libs=>libs, :reqs=>reqs, :live=>live )
|
85
|
+
|
86
|
+
unless pbar
|
87
|
+
puts r.passed? ? "[PASS]" : "[FAIL]"
|
88
|
+
end
|
89
|
+
|
90
|
+
results << r
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
pbar.finish if pbar
|
95
|
+
|
96
|
+
# display results
|
97
|
+
puts results
|
98
|
+
|
99
|
+
fails, errrs = results.failure_count, results.error_count
|
100
|
+
#CHECKLIST << :test if fails > 0
|
101
|
+
#CHECKLIST << :test if errrs > 0
|
102
|
+
return (fails + errrs > 0)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Run a test in a separate process.
|
106
|
+
#
|
107
|
+
# Currently send program output to null device.
|
108
|
+
# Could send to a logger in future version.
|
109
|
+
#
|
110
|
+
# Key parameters are libs, reqs, live.
|
111
|
+
|
112
|
+
def fork_test( file, xfile, keys )
|
113
|
+
keys = keys.rekey(:to_s)
|
114
|
+
|
115
|
+
libs = keys['lib'] || []
|
116
|
+
reqs = keys['req'] || []
|
117
|
+
live = keys['live']
|
118
|
+
|
119
|
+
src = ''
|
120
|
+
|
121
|
+
unless live
|
122
|
+
l = File.join( Dir.pwd, 'lib' )
|
123
|
+
if File.directory?( l )
|
124
|
+
src << %{$:.unshift('#{l}')\n}
|
125
|
+
end
|
126
|
+
libs.each { |r| src << %{$:.unshift('#{r}')\n} }
|
127
|
+
end
|
128
|
+
|
129
|
+
src << %{
|
130
|
+
#require 'test/unit'
|
131
|
+
require 'test/unit/collector'
|
132
|
+
require 'test/unit/collector/objectspace'
|
133
|
+
require 'test/unit/ui/testrunnermediator'
|
134
|
+
}
|
135
|
+
|
136
|
+
reqs.each do |fix|
|
137
|
+
src << %Q{
|
138
|
+
require '#{fix}'
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
src << %{
|
143
|
+
def warn(*null); end # silence warnings
|
144
|
+
|
145
|
+
output = STDOUT.dup
|
146
|
+
STDOUT.reopen( PLATFORM =~ /mswin/ ? "NUL" : "/dev/null" )
|
147
|
+
|
148
|
+
load('#{file}')
|
149
|
+
load('#{xfile}')
|
150
|
+
|
151
|
+
tests = Test::Unit::Collector::ObjectSpace.new.collect
|
152
|
+
runner = Test::Unit::UI::TestRunnerMediator.new( tests )
|
153
|
+
result = runner.run_suite
|
154
|
+
|
155
|
+
begin
|
156
|
+
marshalled = Marshal.dump(result)
|
157
|
+
rescue TypeError => e
|
158
|
+
$stderr << "MARSHAL ERROR\n"
|
159
|
+
$stderr << "TEST: #{file}\n"
|
160
|
+
$stderr << "XTEST: #{xfile}\n"
|
161
|
+
$stderr << "DATA:" << result.inspect
|
162
|
+
exit -1
|
163
|
+
end
|
164
|
+
output << marshalled
|
165
|
+
|
166
|
+
STDOUT.reopen(output)
|
167
|
+
output.close
|
168
|
+
}
|
169
|
+
|
170
|
+
result = IO.popen("ruby","w+") do |ruby|
|
171
|
+
ruby.puts src
|
172
|
+
ruby.close_write
|
173
|
+
ruby.read
|
174
|
+
end
|
175
|
+
|
176
|
+
begin
|
177
|
+
marsh = Marshal.load(result)
|
178
|
+
rescue ArgumentError
|
179
|
+
$stderr << "\nCannot load marshalled test data.\n"
|
180
|
+
$stderr << result << "\n"
|
181
|
+
exit -1
|
182
|
+
end
|
183
|
+
|
184
|
+
return marsh
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# Support class for collecting test results.
|
189
|
+
#
|
190
|
+
|
191
|
+
class TestResults
|
192
|
+
attr_reader :assertion_count,
|
193
|
+
:run_count,
|
194
|
+
:failure_count,
|
195
|
+
:error_count
|
196
|
+
|
197
|
+
attr_accessor :style
|
198
|
+
|
199
|
+
def initialize( style=nil )
|
200
|
+
@style = style
|
201
|
+
|
202
|
+
@results = []
|
203
|
+
|
204
|
+
@assertion_count = 0
|
205
|
+
@run_count = 0
|
206
|
+
@failure_count = 0
|
207
|
+
@error_count = 0
|
208
|
+
end
|
209
|
+
|
210
|
+
# Add a result to the results collection.
|
211
|
+
|
212
|
+
def <<( result )
|
213
|
+
@results << result
|
214
|
+
|
215
|
+
@assertion_count += result.assertion_count
|
216
|
+
@run_count += result.run_count
|
217
|
+
@failure_count += result.failure_count
|
218
|
+
@error_count += result.error_count
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
|
223
|
+
def errors
|
224
|
+
errors = []
|
225
|
+
@results.each do |r|
|
226
|
+
unless r.passed?
|
227
|
+
errors << r.instance_variable_get('@errors')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
errors.reject! { |e| e == [] }
|
231
|
+
errors
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
|
236
|
+
def failures
|
237
|
+
failures = []
|
238
|
+
@results.each do |r|
|
239
|
+
unless r.passed?
|
240
|
+
failures << r.instance_variable_get('@failures')
|
241
|
+
end
|
242
|
+
end
|
243
|
+
failures.reject! { |e| e == [] }
|
244
|
+
failures
|
245
|
+
end
|
246
|
+
|
247
|
+
# Output format for test results.
|
248
|
+
|
249
|
+
def to_s
|
250
|
+
return @results.to_s if style == 'pease'
|
251
|
+
|
252
|
+
s = []
|
253
|
+
# Display failures
|
254
|
+
unless failures.empty?
|
255
|
+
s << ''
|
256
|
+
s << "FAILURES:"
|
257
|
+
failures.reverse.each do |fails|
|
258
|
+
fails.reverse.each do |failure|
|
259
|
+
#puts
|
260
|
+
s << %{ - test : #{failure.test_name}}
|
261
|
+
s << %{ location : #{failure.location}}
|
262
|
+
if failure.message.index("\n")
|
263
|
+
s << %{ message : >}
|
264
|
+
s << failure.message.tabto(6)
|
265
|
+
else
|
266
|
+
s << %{ message : #{failure.message}}
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# Display errors
|
273
|
+
unless errors.empty?
|
274
|
+
s << ''
|
275
|
+
s << "ERRORS:"
|
276
|
+
errors.reverse.each do |errs|
|
277
|
+
errs.reverse.each do |err|
|
278
|
+
s << ''
|
279
|
+
s << %{ - test : #{err.test_name}}
|
280
|
+
s << %{ message : #{err.exception.message}}
|
281
|
+
s << %{ backtrace :}
|
282
|
+
err.exception.backtrace[0...-1].each { |bt| s << %Q{ - #{bt}} }
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# Display final results
|
288
|
+
s << ''
|
289
|
+
s << "Summary:"
|
290
|
+
s << " Tests : #{@run_count}"
|
291
|
+
s << " Assertions : #{@assertion_count}"
|
292
|
+
s << " Failures : #{@failure_count}"
|
293
|
+
s << " Errors : #{@error_count}"
|
294
|
+
s << ''
|
295
|
+
s << ''
|
296
|
+
|
297
|
+
return s.join("\n")
|
298
|
+
end
|
299
|
+
|
300
|
+
# Delegate missing call to the results array.
|
301
|
+
|
302
|
+
def method_missing(*a,&b)
|
303
|
+
@results.send(*a,&b)
|
304
|
+
end
|
305
|
+
end
|