piggly 1.2.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|