piggly 1.2.1 → 2.0.0
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.
- checksums.yaml +7 -0
- data/README.md +163 -0
- data/Rakefile +29 -15
- data/bin/piggly +4 -244
- data/lib/piggly.rb +19 -17
- data/lib/piggly/command.rb +9 -0
- data/lib/piggly/command/base.rb +148 -0
- data/lib/piggly/command/report.rb +162 -0
- data/lib/piggly/command/test.rb +157 -0
- data/lib/piggly/command/trace.rb +90 -0
- data/lib/piggly/command/untrace.rb +78 -0
- data/lib/piggly/compiler.rb +7 -5
- data/lib/piggly/compiler/cache_dir.rb +119 -0
- data/lib/piggly/compiler/coverage_report.rb +63 -0
- data/lib/piggly/compiler/trace_compiler.rb +105 -0
- data/lib/piggly/config.rb +47 -22
- data/lib/piggly/dumper.rb +9 -0
- data/lib/piggly/dumper/index.rb +121 -0
- data/lib/piggly/dumper/qualified_name.rb +36 -0
- data/lib/piggly/dumper/qualified_type.rb +81 -0
- data/lib/piggly/dumper/reified_procedure.rb +142 -0
- data/lib/piggly/dumper/skeleton_procedure.rb +102 -0
- data/lib/piggly/installer.rb +84 -42
- data/lib/piggly/parser.rb +43 -49
- data/lib/piggly/parser/grammar.tt +289 -313
- data/lib/piggly/parser/nodes.rb +270 -211
- data/lib/piggly/parser/traversal.rb +35 -33
- data/lib/piggly/parser/treetop_ruby19_patch.rb +1 -1
- data/lib/piggly/profile.rb +81 -60
- data/lib/piggly/reporter.rb +5 -18
- data/lib/piggly/reporter/base.rb +103 -0
- data/lib/piggly/reporter/html_dsl.rb +63 -0
- data/lib/piggly/reporter/index.rb +108 -0
- data/lib/piggly/reporter/procedure.rb +104 -0
- data/lib/piggly/reporter/resources/highlight.js +21 -0
- data/lib/piggly/reporter/{piggly.css → resources/piggly.css} +52 -12
- data/lib/piggly/reporter/{sortable.js → resources/sortable.js} +0 -0
- data/lib/piggly/tags.rb +280 -0
- data/lib/piggly/task.rb +191 -40
- data/lib/piggly/util.rb +8 -27
- data/lib/piggly/util/blankslate.rb +114 -0
- data/lib/piggly/util/cacheable.rb +19 -0
- data/lib/piggly/util/enumerable.rb +44 -0
- data/lib/piggly/util/file.rb +17 -0
- data/lib/piggly/util/process_queue.rb +96 -0
- data/lib/piggly/util/thunk.rb +39 -0
- data/lib/piggly/version.rb +8 -8
- data/spec/examples/compiler/cacheable_spec.rb +190 -0
- data/spec/examples/compiler/report_spec.rb +25 -0
- data/spec/{compiler → examples/compiler}/trace_spec.rb +7 -57
- data/spec/examples/config_spec.rb +61 -0
- data/spec/examples/dumper/index_spec.rb +197 -0
- data/spec/examples/dumper/procedure_spec.rb +116 -0
- data/spec/{grammar → examples/grammar}/expression_spec.rb +60 -60
- data/spec/{grammar → examples/grammar}/statements/assignment_spec.rb +15 -15
- data/spec/examples/grammar/statements/declaration_spec.rb +21 -0
- data/spec/{grammar → examples/grammar}/statements/exception_spec.rb +10 -10
- data/spec/{grammar → examples/grammar}/statements/if_spec.rb +47 -34
- data/spec/{grammar → examples/grammar}/statements/loop_spec.rb +5 -5
- data/spec/{grammar → examples/grammar}/statements/sql_spec.rb +11 -11
- data/spec/{grammar → examples/grammar}/tokens/comment_spec.rb +11 -11
- data/spec/{grammar → examples/grammar}/tokens/datatype_spec.rb +14 -8
- data/spec/{grammar → examples/grammar}/tokens/identifier_spec.rb +26 -10
- data/spec/{grammar → examples/grammar}/tokens/keyword_spec.rb +5 -5
- data/spec/{grammar → examples/grammar}/tokens/label_spec.rb +7 -7
- data/spec/{grammar → examples/grammar}/tokens/literal_spec.rb +1 -1
- data/spec/examples/grammar/tokens/lval_spec.rb +50 -0
- data/spec/{grammar → examples/grammar}/tokens/number_spec.rb +1 -1
- data/spec/{grammar → examples/grammar}/tokens/sqlkeywords_spec.rb +1 -1
- data/spec/{grammar → examples/grammar}/tokens/string_spec.rb +9 -9
- data/spec/{grammar → examples/grammar}/tokens/whitespace_spec.rb +1 -1
- data/spec/examples/installer_spec.rb +59 -0
- data/spec/examples/parser/nodes_spec.rb +73 -0
- data/spec/examples/parser/traversal_spec.rb +14 -0
- data/spec/examples/parser_spec.rb +115 -0
- data/spec/examples/profile_spec.rb +153 -0
- data/spec/{reporter/html_spec.rb → examples/reporter/html/dsl_spec.rb} +0 -0
- data/spec/examples/reporter/html/index_spec.rb +0 -0
- data/spec/examples/reporter/html_spec.rb +1 -0
- data/spec/examples/reporter_spec.rb +0 -0
- data/spec/{compiler → examples}/tags_spec.rb +10 -10
- data/spec/examples/task_spec.rb +0 -0
- data/spec/examples/util/cacheable_spec.rb +41 -0
- data/spec/examples/util/enumerable_spec.rb +64 -0
- data/spec/examples/util/file_spec.rb +40 -0
- data/spec/examples/util/process_queue_spec.rb +16 -0
- data/spec/examples/util/thunk_spec.rb +58 -0
- data/spec/examples/version_spec.rb +0 -0
- data/spec/issues/007_spec.rb +25 -0
- data/spec/issues/008_spec.rb +73 -0
- data/spec/issues/018_spec.rb +25 -0
- data/spec/spec_helper.rb +253 -9
- metadata +136 -93
- data/README.markdown +0 -116
- data/lib/piggly/compiler/cache.rb +0 -151
- data/lib/piggly/compiler/pretty.rb +0 -67
- data/lib/piggly/compiler/queue.rb +0 -46
- data/lib/piggly/compiler/tags.rb +0 -244
- data/lib/piggly/compiler/trace.rb +0 -91
- data/lib/piggly/filecache.rb +0 -40
- data/lib/piggly/parser/parser.rb +0 -11794
- data/lib/piggly/reporter/html.rb +0 -207
- data/spec/compiler/cache_spec.rb +0 -9
- data/spec/compiler/pretty_spec.rb +0 -9
- data/spec/compiler/queue_spec.rb +0 -3
- data/spec/compiler/rewrite_spec.rb +0 -3
- data/spec/config_spec.rb +0 -58
- data/spec/filecache_spec.rb +0 -70
- data/spec/fixtures/snippets.sql +0 -158
- data/spec/grammar/tokens/lval_spec.rb +0 -50
- data/spec/parser_spec.rb +0 -8
- data/spec/profile_spec.rb +0 -5
data/lib/piggly.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require File.join(PIGGLY_ROOT, 'version')
|
8
|
-
require File.join(PIGGLY_ROOT, 'config')
|
9
|
-
require File.join(PIGGLY_ROOT, 'filecache')
|
10
|
-
require File.join(PIGGLY_ROOT, 'compiler')
|
11
|
-
require File.join(PIGGLY_ROOT, 'parser')
|
12
|
-
require File.join(PIGGLY_ROOT, 'profile')
|
13
|
-
require File.join(PIGGLY_ROOT, 'installer')
|
14
|
-
require File.join(PIGGLY_ROOT, 'reporter')
|
15
|
-
require File.join(PIGGLY_ROOT, 'util')
|
1
|
+
require "erb"
|
2
|
+
require "yaml"
|
3
|
+
require "optparse"
|
4
|
+
require "fileutils"
|
5
|
+
require "digest/md5"
|
6
|
+
require "set"
|
16
7
|
|
17
|
-
|
18
|
-
|
8
|
+
module Piggly
|
9
|
+
autoload :VERSION, "piggly/version"
|
10
|
+
autoload :Config, "piggly/config"
|
11
|
+
autoload :Command, "piggly/command"
|
12
|
+
autoload :Compiler, "piggly/compiler"
|
13
|
+
autoload :Dumper, "piggly/dumper"
|
14
|
+
autoload :Parser, "piggly/parser"
|
15
|
+
autoload :Profile, "piggly/profile"
|
16
|
+
autoload :Installer, "piggly/installer"
|
17
|
+
autoload :Reporter, "piggly/reporter"
|
18
|
+
autoload :Tags, "piggly/tags"
|
19
|
+
autoload :Util, "piggly/util"
|
20
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module Piggly
|
2
|
+
module Command
|
3
|
+
|
4
|
+
class Base
|
5
|
+
end
|
6
|
+
|
7
|
+
class << Base
|
8
|
+
|
9
|
+
def main(argv)
|
10
|
+
cmd, argv = command(argv)
|
11
|
+
|
12
|
+
if cmd.nil?
|
13
|
+
abort "usage: #{$0} {test|report|trace|untrace} --help"
|
14
|
+
else
|
15
|
+
cmd.main(argv)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# @return [(Class, Array<String>)]
|
22
|
+
def command(argv)
|
23
|
+
return if argv.empty?
|
24
|
+
head, *tail = argv
|
25
|
+
|
26
|
+
case head.downcase
|
27
|
+
when "report"; [Report, tail]
|
28
|
+
when "test"; [Test, tail]
|
29
|
+
when "trace"; [Trace, tail]
|
30
|
+
when "untrace"; [Untrace, tail]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [PGconn]
|
35
|
+
def connect(config)
|
36
|
+
require "pg"
|
37
|
+
require "erb"
|
38
|
+
|
39
|
+
files = Array(config.database_yml ||
|
40
|
+
%w(piggly/database.yml
|
41
|
+
config/database.yml
|
42
|
+
piggly/database.json
|
43
|
+
config/database.json))
|
44
|
+
|
45
|
+
path = files.find{|x| File.exists?(x) } or
|
46
|
+
raise "No database config files found: #{files.join(", ")}"
|
47
|
+
|
48
|
+
specs =
|
49
|
+
if File.extname(path) == ".json"
|
50
|
+
require "json"
|
51
|
+
JSON.load(ERB.new(IO.read(path)).result)
|
52
|
+
else
|
53
|
+
require "yaml"
|
54
|
+
YAML.load(ERB.new(IO.read(path)).result)
|
55
|
+
end
|
56
|
+
|
57
|
+
spec = (specs.is_a?(Hash) and specs[config.connection_name]) or
|
58
|
+
raise "Database '#{config.connection_name}' is not configured in #{path}"
|
59
|
+
|
60
|
+
PGconn.connect(spec["host"], spec["port"], nil, nil,
|
61
|
+
spec["database"], spec["username"], spec["password"])
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Enumerable<SkeletonProcedure>]
|
65
|
+
def filter(config, index)
|
66
|
+
if config.filters.empty?
|
67
|
+
index.procedures
|
68
|
+
else
|
69
|
+
head, _ = config.filters
|
70
|
+
|
71
|
+
start =
|
72
|
+
case head.first
|
73
|
+
when :+; []
|
74
|
+
when :-; index.procedures
|
75
|
+
end
|
76
|
+
|
77
|
+
config.filters.inject(start) do |s, pair|
|
78
|
+
case pair.first
|
79
|
+
when :+
|
80
|
+
s | index.procedures.select(&pair.last)
|
81
|
+
when :-
|
82
|
+
s.reject(&pair.last)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def o_accumulate(config)
|
89
|
+
lambda{|x| config.accumulate = x }
|
90
|
+
end
|
91
|
+
|
92
|
+
def o_cache_root(config)
|
93
|
+
lambda{|x| config.cache_root = x }
|
94
|
+
end
|
95
|
+
|
96
|
+
def o_report_root(config)
|
97
|
+
lambda{|x| config.report_root = x }
|
98
|
+
end
|
99
|
+
|
100
|
+
def o_include_paths(config)
|
101
|
+
lambda{|x| config.include_paths.concat(x.split(":")) }
|
102
|
+
end
|
103
|
+
|
104
|
+
def o_database_yml(config)
|
105
|
+
lambda{|x| config.database_yml = x }
|
106
|
+
end
|
107
|
+
|
108
|
+
def o_connection_name(config)
|
109
|
+
lambda{|x| config.connection_name = x }
|
110
|
+
end
|
111
|
+
|
112
|
+
def o_version(config)
|
113
|
+
lambda { puts "piggly #{VERSION} #{VERSION::RELEASE_DATE}"; exit! }
|
114
|
+
end
|
115
|
+
|
116
|
+
def o_dry_run(config)
|
117
|
+
lambda { config.dry_run = true }
|
118
|
+
end
|
119
|
+
|
120
|
+
def o_select(config)
|
121
|
+
lambda do |x|
|
122
|
+
filter =
|
123
|
+
if m = x.match(%r{^/([^/]+)/$})
|
124
|
+
lambda{|p| p.name.to_s.match(m.captures.first) }
|
125
|
+
else
|
126
|
+
lambda{|p| p.name.to_s === x }
|
127
|
+
end
|
128
|
+
|
129
|
+
config.filters << [:+, filter]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def o_reject(config)
|
134
|
+
lambda do |x|
|
135
|
+
filter =
|
136
|
+
if m = x.match(%r{^/([^/]+)/$})
|
137
|
+
lambda{|p| p.name.to_s.match(m.captures.first) }
|
138
|
+
else
|
139
|
+
lambda{|p| p.name.to_s === x }
|
140
|
+
end
|
141
|
+
|
142
|
+
config.filters << [:-, filter]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module Piggly
|
2
|
+
module Command
|
3
|
+
|
4
|
+
#
|
5
|
+
# This command reads a given file (or STDIN) which is expected to contain messages like the
|
6
|
+
# pattern Profile::PATTERN, which is probbaly "WARNING: PIGGLY 0123456789abcdef".
|
7
|
+
#
|
8
|
+
# Lines in the input that match this pattern are profiled and used to generate a report
|
9
|
+
#
|
10
|
+
class Report < Base
|
11
|
+
end
|
12
|
+
|
13
|
+
class << Report
|
14
|
+
def main(argv)
|
15
|
+
require "pp"
|
16
|
+
io, config = configure(argv)
|
17
|
+
|
18
|
+
profile = Profile.new
|
19
|
+
index = Dumper::Index.new(config)
|
20
|
+
|
21
|
+
procedures = filter(config, index)
|
22
|
+
|
23
|
+
if procedures.empty?
|
24
|
+
if filters.empty?
|
25
|
+
abort "no stored procedures in the cache"
|
26
|
+
else
|
27
|
+
abort "no stored procedures in the cache matched your criteria"
|
28
|
+
end
|
29
|
+
elsif config.dry_run?
|
30
|
+
puts procedures.map{|p| p.signature }
|
31
|
+
exit 0
|
32
|
+
end
|
33
|
+
|
34
|
+
profile_procedures(config, procedures, profile)
|
35
|
+
clear_coverage(config, profile)
|
36
|
+
|
37
|
+
read_profile(config, io, profile)
|
38
|
+
store_coverage(profile)
|
39
|
+
|
40
|
+
create_index(config, index, procedures, profile)
|
41
|
+
create_reports(config, procedures, profile)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Adds the given procedures to Profile
|
45
|
+
#
|
46
|
+
def profile_procedures(config, procedures, profile)
|
47
|
+
# register each procedure in the Profile
|
48
|
+
compiler = Compiler::TraceCompiler.new(config)
|
49
|
+
procedures.each do |p|
|
50
|
+
result = compiler.compile(p)
|
51
|
+
profile.add(p, result[:tags], result)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Clear coverage after procedures have been loaded
|
56
|
+
#
|
57
|
+
def clear_coverage(config, profile)
|
58
|
+
unless config.accumulate?
|
59
|
+
puts "clearing previous coverage"
|
60
|
+
profile.clear
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Reads +io+ for lines matching Profile::PATTERN and records coverage
|
65
|
+
#
|
66
|
+
def read_profile(config, io, profile)
|
67
|
+
np = profile.notice_processor(config)
|
68
|
+
io.each{|line| np.call(line) }
|
69
|
+
end
|
70
|
+
|
71
|
+
# Store the coverage Profile on disk
|
72
|
+
#
|
73
|
+
def store_coverage(profile)
|
74
|
+
puts "storing coverage profile"
|
75
|
+
profile.store
|
76
|
+
end
|
77
|
+
|
78
|
+
# Create the report's index.html
|
79
|
+
#
|
80
|
+
def create_index(config, index, procedures, profile)
|
81
|
+
puts "creating index"
|
82
|
+
reporter = Reporter::Index.new(config, profile)
|
83
|
+
reporter.install("resources/piggly.css", "resources/sortable.js", "resources/highlight.js")
|
84
|
+
reporter.report(procedures, index)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Create each procedures' HTML report page
|
88
|
+
#
|
89
|
+
def create_reports(config, procedures, profile)
|
90
|
+
puts "creating reports"
|
91
|
+
queue = Util::ProcessQueue.new
|
92
|
+
|
93
|
+
compiler = Compiler::TraceCompiler.new(config)
|
94
|
+
reporter = Reporter::Procedure.new(config, profile)
|
95
|
+
|
96
|
+
Parser.parser
|
97
|
+
|
98
|
+
procedures.each do |p|
|
99
|
+
queue.add do
|
100
|
+
unless compiler.stale?(p)
|
101
|
+
data = compiler.compile(p)
|
102
|
+
path = reporter.report_path(p.source_path(config), ".html")
|
103
|
+
|
104
|
+
unless profile.empty?(data[:tags])
|
105
|
+
changes = ": #{profile.difference(p, data[:tags])}"
|
106
|
+
end
|
107
|
+
|
108
|
+
puts "reporting coverage for #{p.name}#{changes}"
|
109
|
+
# pp data[:tags]
|
110
|
+
# pp profile[p]
|
111
|
+
# puts
|
112
|
+
|
113
|
+
reporter.report(p)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
queue.execute
|
119
|
+
end
|
120
|
+
|
121
|
+
def configure(argv, config = Config.new)
|
122
|
+
io = $stdin
|
123
|
+
p = OptionParser.new do |o|
|
124
|
+
o.on("-t", "--dry-run", "only print the names of matching procedures", &o_dry_run(config))
|
125
|
+
o.on("-s", "--select PATTERN", "select procedures matching PATTERN", &o_select(config))
|
126
|
+
o.on("-r", "--reject PATTERN", "ignore procedures matching PATTERN", &o_reject(config))
|
127
|
+
o.on("-c", "--cache-root PATH", "local cache directory", &o_cache_root(config))
|
128
|
+
o.on("-o", "--report-root PATH", "report output directory", &o_report_root(config))
|
129
|
+
o.on("-a", "--accumulate", "accumulate data from the previous run", &o_accumulate(config))
|
130
|
+
o.on("-V", "--version", "show version", &o_version(config))
|
131
|
+
o.on("-h", "--help", "show this message") { abort o.to_s }
|
132
|
+
o.on("-f", "--input PATH", "read trace messages from PATH") do |path|
|
133
|
+
io = if path == "-"
|
134
|
+
$stdin
|
135
|
+
else
|
136
|
+
File.open(path, "rb")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
begin
|
142
|
+
p.parse! argv
|
143
|
+
|
144
|
+
if io.eql?($stdin) and $stdin.tty?
|
145
|
+
raise OptionParser::MissingArgument,
|
146
|
+
"stdin must be a pipe, or use --input PATH"
|
147
|
+
end
|
148
|
+
|
149
|
+
return io, config
|
150
|
+
rescue OptionParser::InvalidOption,
|
151
|
+
OptionParser::InvalidArgument,
|
152
|
+
OptionParser::MissingArgument
|
153
|
+
puts p
|
154
|
+
puts
|
155
|
+
puts $!
|
156
|
+
exit! 1
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Piggly
|
2
|
+
module Command
|
3
|
+
|
4
|
+
#
|
5
|
+
# This command handles all the setup and teardown for running Ruby tests, that can
|
6
|
+
# otherwise be accomplished in a more manual fashion, using the other commands. It
|
7
|
+
# assumes that the test files will automatically establish a connection to the correct
|
8
|
+
# database when they are loaded (this is the case for Rails).
|
9
|
+
#
|
10
|
+
module Test
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def main(argv)
|
14
|
+
benchmark do
|
15
|
+
tests, filters = parse_options(argv)
|
16
|
+
profile = Profile.new
|
17
|
+
|
18
|
+
# don't let rspec get these when loading spec files
|
19
|
+
ARGV.clear
|
20
|
+
|
21
|
+
load_tests(tests)
|
22
|
+
Command.connect_to_database
|
23
|
+
|
24
|
+
procedures = dump_procedures(filters)
|
25
|
+
|
26
|
+
if procedures.empty?
|
27
|
+
abort "No stored procedures in the database#{' matched your criteria' if filters.any?}"
|
28
|
+
end
|
29
|
+
|
30
|
+
result =
|
31
|
+
begin
|
32
|
+
trace(procedures)
|
33
|
+
clear_coverage
|
34
|
+
execute_tests
|
35
|
+
ensure
|
36
|
+
untrace(procedures)
|
37
|
+
end
|
38
|
+
|
39
|
+
create_index(procedures)
|
40
|
+
create_reports(procedures)
|
41
|
+
store_coverage
|
42
|
+
|
43
|
+
exit! result # avoid running tests again
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def benchmark
|
50
|
+
start = Time.now
|
51
|
+
value = yield
|
52
|
+
puts " > Completed in #{'%0.2f' % (Time.now - start)} seconds"
|
53
|
+
return value
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Parses command-line options
|
58
|
+
#
|
59
|
+
def parse_options(argv)
|
60
|
+
filters = []
|
61
|
+
|
62
|
+
opts = OptionParser.new do |opts|
|
63
|
+
opts.on("-I", "--include PATHS", "Prepend paths to $LOAD_PATH (colon separated list)", &Command.method(:opt_include_path))
|
64
|
+
opts.on("-o", "--report-root PATH", "Report output directory", &Command.method(:opt_report_root))
|
65
|
+
opts.on("-c", "--cache-root PATH", "Local cache directory", &Command.method(:opt_cache_root))
|
66
|
+
|
67
|
+
opts.on("-n", "--name PATTERN", "Trace stored procedures matching PATTERN") do |opt|
|
68
|
+
if m = opt.match(%r{^/(.+)/$})
|
69
|
+
filters << lambda{|p| p.name.match(m.captures.first) }
|
70
|
+
else
|
71
|
+
filters << lambda{|p| p.name === opt }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("-a", "--aggregate", "Aggregate data from the previous run", &Command.method(:opt_aggregate))
|
76
|
+
opts.on("-V", "--version", "Show version", &Command.method(:opt_version))
|
77
|
+
opts.on("-h", "--help", "Show this message") do
|
78
|
+
puts opts
|
79
|
+
exit! 0
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
begin
|
84
|
+
opts.parse! argv
|
85
|
+
raise OptionParser::MissingArgument, "no tests specified" if argv.empty?
|
86
|
+
rescue OptionParser::InvalidOption,
|
87
|
+
OptionParser::InvalidArgument,
|
88
|
+
OptionParser::MissingArgument
|
89
|
+
puts opts
|
90
|
+
puts
|
91
|
+
puts $!
|
92
|
+
|
93
|
+
exit! 1
|
94
|
+
end
|
95
|
+
|
96
|
+
test_paths = argv.map{|p| Dir[p] }.flatten.sort
|
97
|
+
|
98
|
+
return test_paths, filters
|
99
|
+
end
|
100
|
+
|
101
|
+
def load_tests(tests)
|
102
|
+
puts "Loading #{tests.size} test files"
|
103
|
+
benchmark { tests.each{|file| load file }}
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Writes all stored procedures in the database to disk
|
108
|
+
#
|
109
|
+
def dump_procedures(filters)
|
110
|
+
Command::Trace.dump_procedures(filters)
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Compiles all the stored procedures on disk and installs them
|
115
|
+
#
|
116
|
+
def trace(procedures)
|
117
|
+
benchmark { Command::Trace.trace(procedures) }
|
118
|
+
end
|
119
|
+
|
120
|
+
def clear_coverage
|
121
|
+
Command::Report.clear_coverage
|
122
|
+
end
|
123
|
+
|
124
|
+
def execute_tests
|
125
|
+
if defined? ::Test::Unit::AutoRunner
|
126
|
+
::Test::Unit::AutoRunner.run
|
127
|
+
elsif defined? ::RSpec::Core
|
128
|
+
::Rspec::Core::Runner.run(ARGV, $stderr, $stdout)
|
129
|
+
elsif defined? ::Spec::Runner
|
130
|
+
::Spec::Runner.run
|
131
|
+
elsif defined? ::MiniTest::Unit
|
132
|
+
::MiniTest::Unit.new.run(ARGV)
|
133
|
+
else
|
134
|
+
raise "Neither Test::Unit, MiniTest, nor RSpec were detected"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def store_coverage(profile)
|
139
|
+
benchmark { Command::Report.store_coverage(profile) }
|
140
|
+
end
|
141
|
+
|
142
|
+
def untrace(procedures)
|
143
|
+
benchmark { Command::Untrace.untrace(procedures) }
|
144
|
+
end
|
145
|
+
|
146
|
+
def create_index(procedures, profile)
|
147
|
+
benchmark { Command::Report.create_index(procedures, profile) }
|
148
|
+
end
|
149
|
+
|
150
|
+
def create_reports(procedures, profile)
|
151
|
+
benchmark { Command::Report.create_reports(procedures, profile) }
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|