piggly 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +163 -0
  3. data/Rakefile +29 -15
  4. data/bin/piggly +4 -244
  5. data/lib/piggly.rb +19 -17
  6. data/lib/piggly/command.rb +9 -0
  7. data/lib/piggly/command/base.rb +148 -0
  8. data/lib/piggly/command/report.rb +162 -0
  9. data/lib/piggly/command/test.rb +157 -0
  10. data/lib/piggly/command/trace.rb +90 -0
  11. data/lib/piggly/command/untrace.rb +78 -0
  12. data/lib/piggly/compiler.rb +7 -5
  13. data/lib/piggly/compiler/cache_dir.rb +119 -0
  14. data/lib/piggly/compiler/coverage_report.rb +63 -0
  15. data/lib/piggly/compiler/trace_compiler.rb +105 -0
  16. data/lib/piggly/config.rb +47 -22
  17. data/lib/piggly/dumper.rb +9 -0
  18. data/lib/piggly/dumper/index.rb +121 -0
  19. data/lib/piggly/dumper/qualified_name.rb +36 -0
  20. data/lib/piggly/dumper/qualified_type.rb +81 -0
  21. data/lib/piggly/dumper/reified_procedure.rb +142 -0
  22. data/lib/piggly/dumper/skeleton_procedure.rb +102 -0
  23. data/lib/piggly/installer.rb +84 -42
  24. data/lib/piggly/parser.rb +43 -49
  25. data/lib/piggly/parser/grammar.tt +289 -313
  26. data/lib/piggly/parser/nodes.rb +270 -211
  27. data/lib/piggly/parser/traversal.rb +35 -33
  28. data/lib/piggly/parser/treetop_ruby19_patch.rb +1 -1
  29. data/lib/piggly/profile.rb +81 -60
  30. data/lib/piggly/reporter.rb +5 -18
  31. data/lib/piggly/reporter/base.rb +103 -0
  32. data/lib/piggly/reporter/html_dsl.rb +63 -0
  33. data/lib/piggly/reporter/index.rb +108 -0
  34. data/lib/piggly/reporter/procedure.rb +104 -0
  35. data/lib/piggly/reporter/resources/highlight.js +21 -0
  36. data/lib/piggly/reporter/{piggly.css → resources/piggly.css} +52 -12
  37. data/lib/piggly/reporter/{sortable.js → resources/sortable.js} +0 -0
  38. data/lib/piggly/tags.rb +280 -0
  39. data/lib/piggly/task.rb +191 -40
  40. data/lib/piggly/util.rb +8 -27
  41. data/lib/piggly/util/blankslate.rb +114 -0
  42. data/lib/piggly/util/cacheable.rb +19 -0
  43. data/lib/piggly/util/enumerable.rb +44 -0
  44. data/lib/piggly/util/file.rb +17 -0
  45. data/lib/piggly/util/process_queue.rb +96 -0
  46. data/lib/piggly/util/thunk.rb +39 -0
  47. data/lib/piggly/version.rb +8 -8
  48. data/spec/examples/compiler/cacheable_spec.rb +190 -0
  49. data/spec/examples/compiler/report_spec.rb +25 -0
  50. data/spec/{compiler → examples/compiler}/trace_spec.rb +7 -57
  51. data/spec/examples/config_spec.rb +61 -0
  52. data/spec/examples/dumper/index_spec.rb +197 -0
  53. data/spec/examples/dumper/procedure_spec.rb +116 -0
  54. data/spec/{grammar → examples/grammar}/expression_spec.rb +60 -60
  55. data/spec/{grammar → examples/grammar}/statements/assignment_spec.rb +15 -15
  56. data/spec/examples/grammar/statements/declaration_spec.rb +21 -0
  57. data/spec/{grammar → examples/grammar}/statements/exception_spec.rb +10 -10
  58. data/spec/{grammar → examples/grammar}/statements/if_spec.rb +47 -34
  59. data/spec/{grammar → examples/grammar}/statements/loop_spec.rb +5 -5
  60. data/spec/{grammar → examples/grammar}/statements/sql_spec.rb +11 -11
  61. data/spec/{grammar → examples/grammar}/tokens/comment_spec.rb +11 -11
  62. data/spec/{grammar → examples/grammar}/tokens/datatype_spec.rb +14 -8
  63. data/spec/{grammar → examples/grammar}/tokens/identifier_spec.rb +26 -10
  64. data/spec/{grammar → examples/grammar}/tokens/keyword_spec.rb +5 -5
  65. data/spec/{grammar → examples/grammar}/tokens/label_spec.rb +7 -7
  66. data/spec/{grammar → examples/grammar}/tokens/literal_spec.rb +1 -1
  67. data/spec/examples/grammar/tokens/lval_spec.rb +50 -0
  68. data/spec/{grammar → examples/grammar}/tokens/number_spec.rb +1 -1
  69. data/spec/{grammar → examples/grammar}/tokens/sqlkeywords_spec.rb +1 -1
  70. data/spec/{grammar → examples/grammar}/tokens/string_spec.rb +9 -9
  71. data/spec/{grammar → examples/grammar}/tokens/whitespace_spec.rb +1 -1
  72. data/spec/examples/installer_spec.rb +59 -0
  73. data/spec/examples/parser/nodes_spec.rb +73 -0
  74. data/spec/examples/parser/traversal_spec.rb +14 -0
  75. data/spec/examples/parser_spec.rb +115 -0
  76. data/spec/examples/profile_spec.rb +153 -0
  77. data/spec/{reporter/html_spec.rb → examples/reporter/html/dsl_spec.rb} +0 -0
  78. data/spec/examples/reporter/html/index_spec.rb +0 -0
  79. data/spec/examples/reporter/html_spec.rb +1 -0
  80. data/spec/examples/reporter_spec.rb +0 -0
  81. data/spec/{compiler → examples}/tags_spec.rb +10 -10
  82. data/spec/examples/task_spec.rb +0 -0
  83. data/spec/examples/util/cacheable_spec.rb +41 -0
  84. data/spec/examples/util/enumerable_spec.rb +64 -0
  85. data/spec/examples/util/file_spec.rb +40 -0
  86. data/spec/examples/util/process_queue_spec.rb +16 -0
  87. data/spec/examples/util/thunk_spec.rb +58 -0
  88. data/spec/examples/version_spec.rb +0 -0
  89. data/spec/issues/007_spec.rb +25 -0
  90. data/spec/issues/008_spec.rb +73 -0
  91. data/spec/issues/018_spec.rb +25 -0
  92. data/spec/spec_helper.rb +253 -9
  93. metadata +136 -93
  94. data/README.markdown +0 -116
  95. data/lib/piggly/compiler/cache.rb +0 -151
  96. data/lib/piggly/compiler/pretty.rb +0 -67
  97. data/lib/piggly/compiler/queue.rb +0 -46
  98. data/lib/piggly/compiler/tags.rb +0 -244
  99. data/lib/piggly/compiler/trace.rb +0 -91
  100. data/lib/piggly/filecache.rb +0 -40
  101. data/lib/piggly/parser/parser.rb +0 -11794
  102. data/lib/piggly/reporter/html.rb +0 -207
  103. data/spec/compiler/cache_spec.rb +0 -9
  104. data/spec/compiler/pretty_spec.rb +0 -9
  105. data/spec/compiler/queue_spec.rb +0 -3
  106. data/spec/compiler/rewrite_spec.rb +0 -3
  107. data/spec/config_spec.rb +0 -58
  108. data/spec/filecache_spec.rb +0 -70
  109. data/spec/fixtures/snippets.sql +0 -158
  110. data/spec/grammar/tokens/lval_spec.rb +0 -50
  111. data/spec/parser_spec.rb +0 -8
  112. data/spec/profile_spec.rb +0 -5
@@ -1,64 +1,215 @@
1
- require 'rake'
2
- require 'rake/tasklib'
1
+ require "rake"
2
+ require "rake/tasklib"
3
+
4
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), ".."))
5
+ require "piggly"
3
6
 
4
7
  module Piggly
5
- class Task < Rake::TaskLib
8
+
9
+ class AbstractTask < Rake::TaskLib
6
10
  attr_accessor :name, # Name of the test task
7
- :libs, # List of paths added to $LOAD_PATH before running tests
8
- :test_files, # List of ruby test files to load
9
- :proc_files, # List of pl/pgsql stored procedures to compile
10
11
  :verbose,
11
- :warning, # Execute ruby -w if true
12
- :report_dir, # Where to store reports (default piggly/report)
13
- :cache_root, # Where to store compiler cache (default piggly/cache)
14
- :aggregate, # Accumulate coverage from the previous run (default false)
12
+ :ruby_opts
13
+
14
+ attr_accessor :procedures, # List of procedure names or regular expressions, match all by default
15
+ :cache_root, # Where to store cache data
15
16
  :piggly_opts,
16
- :piggly_path # Path to bin/piggly (default searches with ruby -S)
17
+ :piggly_path # Path to bin/piggly
17
18
 
18
19
  def initialize(name = :piggly)
19
- @name = name
20
- @libs = %w[]
21
- @verbose = false
22
- @warning = false
23
- @test_files = []
24
- @proc_files = []
25
- @ruby_opts = []
26
- @report_dir = 'piggly/report'
27
- @cache_root = 'piggly/cache'
28
- @piggly_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'piggly'))
29
- @piggly_opts = ''
30
- @aggregate = false
20
+ @name = name
21
+ @verbose = false
22
+ @ruby_opts = []
23
+
24
+ @procedures = []
25
+ @cache_root = nil
26
+ @piggly_path = File.expand_path("#{File.dirname(__FILE__)}/../../bin/piggly")
27
+ @piggly_opts = []
28
+
31
29
  yield self if block_given?
32
30
  define
33
31
  end
34
32
 
35
- # create tasks defined by this task lib
33
+ private
34
+
35
+ def quote(value)
36
+ case value
37
+ when Regexp
38
+ quote(value.inspect)
39
+ else
40
+ %{"#{value}"}
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ class TraceTask < AbstractTask
47
+ def initialize(name = :trace)
48
+ super(name)
49
+ end
50
+
51
+ private
52
+
36
53
  def define
37
- desc 'Run piggly tests' + (@name == :piggly ? '' : " for #{@name}")
54
+ desc 'Trace stored procedures'
38
55
  task @name do
39
- @piggly_opts << "--aggregate" if @aggregate
56
+ RakeFileUtils.verbose(@verbose) do
57
+ opts = []
58
+ opts << "trace"
59
+ opts.concat(["--cache-root", @cache_root]) if @cache_root
60
+
61
+ case @procedures
62
+ when String then opts.concat(["--name", @procedures])
63
+ when Regexp then opts.concat(["--name", @procedures.inspect])
64
+ when Array
65
+ @procedures.each do |p|
66
+ case p
67
+ when String then opts.concat(["--name", p])
68
+ when Regexp then opts.concat(["--name", p.inspect])
69
+ end
70
+ end
71
+ end
72
+
73
+ opts.concat(@piggly_opts)
74
+ # ruby(opts.join(" "))
75
+ Command.main(opts)
76
+ end
77
+ end
78
+ end
79
+ end
40
80
 
81
+ class UntraceTask < AbstractTask
82
+ def initialize(name = :untrace)
83
+ super(name)
84
+ end
85
+
86
+ private
87
+
88
+ def define
89
+ desc 'Untrace stored procedures'
90
+ task @name do
41
91
  RakeFileUtils.verbose(@verbose) do
42
- run_code = (piggly_path.nil?) ? '-S piggly' : quote(piggly_path)
43
- opts = @ruby_opts.clone
44
- opts.push "-I#{Array(@libs).join(File::PATH_SEPARATOR)}"
45
- opts.push run_code
46
- opts.push '-w' if @warning
47
-
48
- ruby opts.join(' ') + ' ' +
49
- @piggly_opts + ' ' +
50
- %{-o #{quote @report_dir} } +
51
- %{-c #{quote @cache_root} } +
52
- proc_files.map{|s| %[-s "#{s}" ] }.join +
53
- test_files.map{|f| quote(f) }.join(' ')
92
+ # opts = @ruby_opts.clone
93
+ # opts << (@piggly_path ? quote(@piggly_path) : "-S piggly")
94
+ opts = []
95
+ opts << "untrace"
96
+ opts.concat(["--cache-root", @cache_root]) if @cache_root
97
+
98
+ case @procedures
99
+ when String then opts.concat(["--name", @procedures])
100
+ when Regexp then opts.concat(["--name", @procedures.inspect])
101
+ when Array
102
+ @procedures.each do |p|
103
+ case p
104
+ when String then opts.concat(["--name", p])
105
+ when Regexp then opts.concat(["--name", p.inspect])
106
+ end
107
+ end
108
+ end
109
+
110
+ opts.concat(@piggly_opts)
111
+ # ruby(opts.join(" "))
112
+ Command.main(opts)
54
113
  end
114
+ end
115
+ end
116
+ end
117
+
118
+ class ReportTask < AbstractTask
119
+ attr_accessor :report_root, # Where to store reports (default piggly/report)
120
+ :accumulate, # Accumulate coverage from the previous run (default false)
121
+ :trace_file
55
122
 
123
+ def initialize(name = :report)
124
+ @accumulate = false
125
+ @trace_file = nil
126
+ @report_root = nil
127
+ super(name)
128
+ end
129
+
130
+ private
131
+
132
+ def define
133
+ desc 'Generate piggly report'
134
+ task @name do
135
+ RakeFileUtils.verbose(@verbose) do
136
+ # opts = @ruby_opts.clone
137
+ # opts << (@piggly_path ? quote(@piggly_path) : "-S piggly")
138
+ opts = []
139
+ opts << "report"
140
+ opts << "--accumulate" if @accumulate
141
+ opts.concat(["--trace-file", @trace_file])
142
+ opts.concat(["--cache-root", @cache_root]) if @cache_root
143
+ opts.concat(["--report-root", @report_root]) if @report_root
144
+
145
+ case @procedures
146
+ when String then opts.concat(["--name", @procedures])
147
+ when Regexp then opts.concat(["--name", @procedures.inspect])
148
+ when Array
149
+ @procedures.each do |p|
150
+ case p
151
+ when String then opts.concat(["--name", p])
152
+ when Regexp then opts.concat(["--name", p.inspect])
153
+ end
154
+ end
155
+ end
156
+
157
+ opts.concat(@piggly_opts)
158
+ # ruby(opts.join(" "))
159
+ Command.main(opts)
160
+ end
56
161
  end
57
162
  end
163
+ end
164
+
165
+ class TestTask < AbstractTask
166
+ attr_accessor :test_files, # List of ruby test files to load
167
+ :report_root, # Where to store reports (default piggly/report)
168
+ :accumulate # Accumulate coverage from the previous run (default false)
58
169
 
59
- def quote(string)
60
- %{"#{string}"}
170
+ def initialize(name = :piggly)
171
+ @report_root = nil
172
+ @test_files = []
173
+ @accumulate = false
174
+ super(name)
61
175
  end
62
176
 
177
+ private
178
+
179
+ def define
180
+ desc 'Run piggly tests' + (@name == :piggly ? '' : " for #{@name}")
181
+ task @name do
182
+ RakeFileUtils.verbose(@verbose) do
183
+ opts = @ruby_opts.clone
184
+ opts << (@piggly_path ? quote(@piggly_path) : "-S piggly")
185
+ opts << "test"
186
+ opts << "--accumulate" if @accumulate
187
+ opts << "--cache-root #{quote @cache_root}" if @cache_root
188
+ opts << "--report-root #{quote @report_root}" if @report_root
189
+
190
+ case @procedures
191
+ when String then opts << "--name #{quote @procedures}"
192
+ when Regexp then opts << "--name #{quote @procedures.inspect}"
193
+ when Array
194
+ @procedures.each do |p|
195
+ case p
196
+ when String then opts << "--name #{quote p}"
197
+ when Regexp then opts << "--name #{quote p.inspect}"
198
+ end
199
+ end
200
+ end
201
+
202
+ opts.concat(@piggly_opts)
203
+
204
+ unless (@test_files || []).empty?
205
+ opts << "--"
206
+ opts.concat(@test_files.map{|x| quote(x) })
207
+ end
208
+
209
+ ruby(opts.join(" "))
210
+ end
211
+ end
212
+ end
63
213
  end
214
+
64
215
  end
@@ -1,28 +1,9 @@
1
- module Enumerable
2
-
3
- # Count number of elements, optionally filtered by a block
4
- def count
5
- if block_given?
6
- inject(0){|count, x| count + (yield(x) ? 1 : 0) }
7
- else
8
- size
9
- end
10
- end unless method_defined?(:count)
11
-
12
- # Sum elements, optionally transformed by a block
13
- def sum(init = 0)
14
- if block_given?
15
- inject(init){|sum, e| sum + yield(e) }
16
- else
17
- inject(init){|sum, e| sum + e }
18
- end
19
- end unless method_defined?(:sum)
20
-
21
- def group_by(collection = Hash.new{|h,k| h[k] = [] })
22
- inject(collection) do |hash, item|
23
- hash[yield(item)] << item
24
- hash
25
- end
26
- end unless method_defined?(:group_by)
27
-
1
+ module Piggly
2
+ module Util
3
+ autoload :ProcessQueue, "piggly/util/process_queue"
4
+ autoload :Thunk, "piggly/util/thunk"
5
+ autoload :Cacheable, "piggly/util/cacheable"
6
+ autoload :Enumerable, "piggly/util/enumerable"
7
+ autoload :File, "piggly/util/file"
8
+ end
28
9
  end
@@ -0,0 +1,114 @@
1
+ unless defined? BlankSlate
2
+ #--
3
+ # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+
11
+ ######################################################################
12
+ # BlankSlate provides an abstract base class with no predefined
13
+ # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
14
+ # BlankSlate is useful as a base class when writing classes that
15
+ # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
16
+ #
17
+ class BlankSlate
18
+ class << self
19
+
20
+ # Hide the method named +name+ in the BlankSlate class. Don't
21
+ # hide +instance_eval+ or any method beginning with "__".
22
+ def hide(name)
23
+ if instance_methods.include?(name.to_s) and
24
+ name !~ /^(__|instance_eval)/
25
+ @hidden_methods ||= {}
26
+ @hidden_methods[name.to_sym] = instance_method(name)
27
+ undef_method name
28
+ end
29
+ end
30
+
31
+ def find_hidden_method(name)
32
+ @hidden_methods ||= {}
33
+ @hidden_methods[name] || superclass.find_hidden_method(name)
34
+ end
35
+
36
+ # Redefine a previously hidden method so that it may be called on a blank
37
+ # slate object.
38
+ def reveal(name)
39
+ bound_method = nil
40
+ unbound_method = find_hidden_method(name)
41
+ fail "Don't know how to reveal method '#{name}'" unless unbound_method
42
+ define_method(name) do |*args|
43
+ bound_method ||= unbound_method.bind(self)
44
+ bound_method.call(*args)
45
+ end
46
+ end
47
+ end
48
+
49
+ instance_methods.each { |m| hide(m) }
50
+ end
51
+
52
+ ######################################################################
53
+ # Since Ruby is very dynamic, methods added to the ancestors of
54
+ # BlankSlate <em>after BlankSlate is defined</em> will show up in the
55
+ # list of available BlankSlate methods. We handle this by defining a
56
+ # hook in the Object and Kernel classes that will hide any method
57
+ # defined after BlankSlate has been loaded.
58
+ #
59
+ module Kernel
60
+ class << self
61
+ alias_method :blank_slate_method_added, :method_added
62
+
63
+ # Detect method additions to Kernel and remove them in the
64
+ # BlankSlate class.
65
+ def method_added(name)
66
+ result = blank_slate_method_added(name)
67
+ return result if self != Kernel
68
+ BlankSlate.hide(name)
69
+ result
70
+ end
71
+ end
72
+ end
73
+
74
+ ######################################################################
75
+ # Same as above, except in Object.
76
+ #
77
+ class Object
78
+ class << self
79
+ alias_method :blank_slate_method_added, :method_added
80
+
81
+ # Detect method additions to Object and remove them in the
82
+ # BlankSlate class.
83
+ def method_added(name)
84
+ result = blank_slate_method_added(name)
85
+ return result if self != Object
86
+ BlankSlate.hide(name)
87
+ result
88
+ end
89
+
90
+ def find_hidden_method(name)
91
+ nil
92
+ end
93
+ end
94
+ end
95
+
96
+ ######################################################################
97
+ # Also, modules included into Object need to be scanned and have their
98
+ # instance methods removed from blank slate. In theory, modules
99
+ # included into Kernel would have to be removed as well, but a
100
+ # "feature" of Ruby prevents late includes into modules from being
101
+ # exposed in the first place.
102
+ #
103
+ class Module
104
+ alias blankslate_original_append_features append_features
105
+ def append_features(mod)
106
+ result = blankslate_original_append_features(mod)
107
+ return result if mod != Object
108
+ instance_methods.each do |name|
109
+ BlankSlate.hide(name)
110
+ end
111
+ result
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,19 @@
1
+ module Piggly
2
+ module Util
3
+ module Cacheable
4
+
5
+ def cache_path(file)
6
+ # Up to the last capitalized word of the class name
7
+ classdir = self.class.name[/^(?:.+::)?(.+?)([A-Z][^A-Z]+)?$/, 1]
8
+
9
+ # md5 the full path to prevent collisions
10
+ full = ::File.expand_path(file)
11
+ hash = Digest::MD5.hexdigest(::File.dirname(full))
12
+ base = ::File.basename(file)
13
+
14
+ @config.mkpath(::File.join(@config.cache_root, classdir), base)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ module Piggly
2
+ module Util
3
+ module Enumerable
4
+
5
+ # Count number of elements, optionally filtered by a block
6
+ def self.count(enum)
7
+ if block_given?
8
+ enum.inject(0){|count,e| yield(e) ? count + 1 : count }
9
+ else
10
+ enum.length
11
+ end
12
+ end
13
+
14
+ # Compute sum of elements, optionally transformed by a block
15
+ def self.sum(enum, default = 0, &block)
16
+ enum = enum.to_a
17
+ return default if enum.empty?
18
+
19
+ head, *tail = enum
20
+
21
+ if block_given?
22
+ tail.inject(yield(head)){|sum,e| sum + yield(e) }
23
+ else
24
+ tail.inject(head){|sum,e| sum + e }
25
+ end
26
+ end
27
+
28
+ # Collect an elements into disjoint sets, grouped by result of the block
29
+ def self.group_by(enum, collection = Hash.new{|h,k| h[k] = [] })
30
+ enum.inject(collection) do |hash, item|
31
+ hash[yield(item)] << item
32
+ hash
33
+ end
34
+ end
35
+
36
+ def self.index_by(enum, collection = Hash.new)
37
+ enum.inject(collection) do |hash, item|
38
+ hash.update(yield(item) => item)
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end