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.
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
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ module Piggly
4
+
5
+ describe Parser::Traversal do
6
+ describe "fold"
7
+ describe "reduce"
8
+ describe "count"
9
+ describe "find"
10
+ describe "select"
11
+ describe "flatten"
12
+ end
13
+
14
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ module Piggly
4
+
5
+ describe Parser do
6
+
7
+ describe "parse" do
8
+ it "returns a thunk" do
9
+ tree = nil
10
+
11
+ lambda do
12
+ tree = Parser.parse('input')
13
+ end.should_not raise_error
14
+
15
+ tree.thunk?.should be_true
16
+ end
17
+
18
+ context "when the thunk is evaluated" do
19
+ before do
20
+ @parser = mock('PigglyParser')
21
+ Parser.stub(:parser).and_return(@parser)
22
+ end
23
+
24
+ it "downcases input string before parsing" do
25
+ input = 'SOURCE CODE'
26
+
27
+ @parser.stub(:failure_reason)
28
+ @parser.should_receive(:parse).
29
+ with(input.downcase)
30
+
31
+ begin
32
+ Parser.parse(input).force!
33
+ rescue Parser::Failure
34
+ # don't care
35
+ end
36
+ end
37
+
38
+ context "when parser fails" do
39
+ it "raises Parser::Failure" do
40
+ input = 'SOURCE CODE'
41
+ reason = 'expecting someone else'
42
+
43
+ @parser.should_receive(:parse).
44
+ and_return(nil)
45
+ @parser.should_receive(:failure_reason).
46
+ and_return(reason)
47
+
48
+ lambda do
49
+ Parser.parse('SOURCE CODE').force!
50
+ end.should raise_error(Parser::Failure, reason)
51
+ end
52
+ end
53
+
54
+ context "when parser succeeds" do
55
+ it "returns parser's result" do
56
+ input = 'SOURCE CODE'
57
+ tree = mock('NodeClass', :message => 'result')
58
+
59
+ @parser.should_receive(:parse).
60
+ and_return(tree)
61
+
62
+ Parser.parse('SOURCE CODE').message.should == tree.message
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+
69
+ describe "parser" do
70
+
71
+ context "when the grammar is older than the generated parser" do
72
+ before do
73
+ Util::File.stub(:stale?).and_return(false)
74
+ end
75
+
76
+ it "does not regenerate the parser" do
77
+ Treetop::Compiler::GrammarCompiler.should_not_receive(:new)
78
+ # Parser.should_receive(:require).
79
+ # with(Parser.parser_path)
80
+
81
+ Parser.parser
82
+ end
83
+
84
+ it "returns an instance of PigglyParser" do
85
+ Parser.parser.should be_a(PigglyParser)
86
+ end
87
+ end
88
+
89
+ context "when the generated parser is older than the grammar" do
90
+ before do
91
+ Util::File.stub(:stale?).and_return(true)
92
+ end
93
+
94
+ it "regenerates the parser and loads it" do
95
+ compiler = mock('GrammarCompiler')
96
+ compiler.should_receive(:compile).
97
+ with(Parser.grammar_path, Parser.parser_path)
98
+
99
+ Treetop::Compiler::GrammarCompiler.should_receive(:new).
100
+ and_return(compiler)
101
+
102
+ Parser.should_receive(:load).
103
+ with(Parser.parser_path)
104
+
105
+ Parser.parser
106
+ end
107
+
108
+ it "returns an instance of PigglyParser" do
109
+ Parser.parser.should be_a(PigglyParser)
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ module Piggly
4
+
5
+ describe Profile do
6
+
7
+ before do
8
+ @profile = Profile.new
9
+ end
10
+
11
+ describe "notice_processor" do
12
+ before do
13
+ @config = mock('config', :trace_prefix => 'PIGGLY')
14
+ @stderr = mock('stderr').as_null_object
15
+ @callback = @profile.notice_processor(@config, @stderr)
16
+ end
17
+
18
+ it "returns a function" do
19
+ @callback.should be_a(Proc)
20
+ end
21
+
22
+ context "when message matches PATTERN" do
23
+ context "with no optional value" do
24
+ it "pings the corresponding tag" do
25
+ message = "WARNING: #{@config.trace_prefix} 0123456789abcdef"
26
+ @profile.should_receive(:ping).
27
+ with('0123456789abcdef', nil)
28
+
29
+ @callback.call(message)
30
+ end
31
+ end
32
+
33
+ context "with an optional value" do
34
+ it "pings the corresponding tag" do
35
+ message = "WARNING: #{@config.trace_prefix} 0123456789abcdef X"
36
+ @profile.should_receive(:ping).
37
+ with('0123456789abcdef', 'X')
38
+
39
+ @callback.call(message)
40
+ end
41
+ end
42
+ end
43
+
44
+ context "when message doesn't match PATTERN" do
45
+ it "prints the message to stderr" do
46
+ message = "WARNING: Parameter was NULL and I don't like it!"
47
+ @stderr.should_receive(:puts).with(message)
48
+ @callback.call(message)
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "add" do
54
+ before do
55
+ @first = mock('first tag', :id => 'first')
56
+ @second = mock('second tag', :id => 'second')
57
+ @third = mock('third tag', :id => 'third')
58
+ @cache = mock('Compiler::Cacheable::CacheDirectory')
59
+
60
+ @procedure = Dumper::SkeletonProcedure.allocate
61
+ @procedure.stub(:oid).and_return('oid')
62
+ end
63
+
64
+ context "without cache parameter" do
65
+ it "indexes each tag by id" do
66
+ @profile.add(@procedure, [@first, @second, @third])
67
+ @profile[@first.id].should == @first
68
+ @profile[@second.id].should == @second
69
+ @profile[@third.id].should == @third
70
+ end
71
+
72
+ it "indexes each tag by procedure" do
73
+ @profile.add(@procedure, [@first, @second, @third])
74
+ @profile[@procedure].should == [@first, @second, @third]
75
+ end
76
+ end
77
+
78
+ context "with cache parameter" do
79
+ it "indexes each tag by id" do
80
+ @profile.add(@procedure, [@first, @second, @third], @cache)
81
+ @profile[@first.id].should == @first
82
+ @profile[@second.id].should == @second
83
+ @profile[@third.id].should == @third
84
+ end
85
+
86
+ it "indexes each tag by procedure" do
87
+ @profile.add(@procedure, [@first, @second, @third])
88
+ @profile[@procedure].should == [@first, @second, @third]
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "ping" do
94
+ context "when tag isn't in the profile" do
95
+ it "raises an exception" do
96
+ lambda do
97
+ @profile.ping('0123456789abcdef')
98
+ end.should raise_error('No tag with id 0123456789abcdef')
99
+ end
100
+ end
101
+
102
+ context "when tag is in the profile" do
103
+ before do
104
+ @tag = mock('tag', :id => '0123456789abcdef')
105
+ procedure = mock('procedure', :oid => nil)
106
+ @profile.add(procedure, [@tag])
107
+ end
108
+
109
+ it "calls ping on the corresponding tag" do
110
+ @tag.should_receive(:ping).with('X')
111
+ @profile.ping(@tag.id, 'X')
112
+ end
113
+ end
114
+ end
115
+
116
+ describe "summary" do
117
+ context "when given a procedure" do
118
+ end
119
+
120
+ context "when not given a procedure" do
121
+ end
122
+ end
123
+
124
+ describe "clear" do
125
+ before do
126
+ @first = mock('first tag', :id => 'first')
127
+ @second = mock('second tag', :id => 'second')
128
+ @third = mock('third tag', :id => 'third')
129
+ procedure = mock('procedure', :oid => nil)
130
+
131
+ @profile.add(procedure, [@first, @second, @third])
132
+ end
133
+
134
+ it "calls clear on each tag" do
135
+ @first.should_receive(:clear)
136
+ @second.should_receive(:clear)
137
+ @third.should_receive(:clear)
138
+ @profile.clear
139
+ end
140
+ end
141
+
142
+ describe "store" do
143
+ end
144
+
145
+ describe "empty?" do
146
+ end
147
+
148
+ describe "difference" do
149
+ end
150
+
151
+ end
152
+
153
+ end
@@ -0,0 +1 @@
1
+ require 'spec_helper'
File without changes
@@ -1,28 +1,28 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  module Piggly
4
4
 
5
- describe Tag do
5
+ describe Tags::AbstractTag do
6
6
  end
7
7
 
8
- describe EvaluationTag do
8
+ describe Tags::EvaluationTag do
9
9
  end
10
10
 
11
- describe BlockTag do
11
+ describe Tags::BlockTag do
12
12
  end
13
13
 
14
- describe UnconditionalBranchTag do
14
+ describe Tags::UnconditionalBranchTag do
15
15
  end
16
16
 
17
- describe LoopConditionTag do
17
+ describe Tags::ConditionalLoopTag do
18
18
  end
19
19
 
20
- describe ForCollectionTag do
20
+ describe Tags::UnconditionalLoopTag do
21
21
  before do
22
- @tag = ForCollectionTag.new('for-loop')
22
+ @tag = Tags::UnconditionalLoopTag.new('for-loop')
23
23
  end
24
24
 
25
- it "detects state 00 (0b0000)" do
25
+ it "starts with state 00 (0b0000)" do
26
26
  # - terminates normally
27
27
  # - pass through
28
28
  # - iterate only once
@@ -279,7 +279,7 @@ describe ForCollectionTag do
279
279
 
280
280
  end
281
281
 
282
- describe BranchConditionTag do
282
+ describe Tags::ConditionalBranchTag do
283
283
  end
284
284
 
285
285
  end
File without changes
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module Piggly
4
+
5
+ =begin
6
+ describe Util::Cacheable do
7
+
8
+ class ExampleClass; include Piggly::Util::Cacheable; end
9
+ class ExampleCacheClass; include Piggly::Util::Cacheable; end
10
+ class PigglyExampleClassHTML; include Piggly::Util::Cacheable; end
11
+ class PigglyExampleHTMLClass; include Piggly::Util::Cacheable; end
12
+ class HTMLPiggly; include Piggly::Util::Cacheable; end
13
+ class ExampleRedefined
14
+ include Piggly::Util::Cacheable
15
+ def self.cache_path(file)
16
+ 'redefined'
17
+ end
18
+ end
19
+
20
+ before do
21
+ Config.stub(:cache_root).and_return('/')
22
+ end
23
+
24
+ it "installs class methods" do
25
+ ExampleClass.should respond_to(:cache_path)
26
+ end
27
+
28
+ it "uses class name as cache subdirectory" do
29
+ FileUtils.should_receive(:makedirs).at_least(:once)
30
+
31
+ ExampleClass.cache_path('a.ext').should =~ %r(/Example/a.ext$)
32
+ ExampleCacheClass.cache_path('a.ext').should =~ %r(/ExampleCache/a.ext$)
33
+ PigglyExampleClassHTML.cache_path('a.ext').should =~ %r(/PigglyExampleClassHTML/a.ext$)
34
+ PigglyExampleHTMLClass.cache_path('a.ext').should =~ %r(/PigglyExampleHTML/a.ext$)
35
+ HTMLPiggly.cache_path('a.ext').should =~ %r(/HTML/a.ext$)
36
+ ExampleRedefined.cache_path('a.ext').should == 'redefined'
37
+ end
38
+ end
39
+ =end
40
+
41
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ module Piggly::Util
4
+
5
+ describe Enumerable do
6
+ before do
7
+ @hash = {:a => '%', :b => '#'}
8
+ @array = %w(a b c d)
9
+ @range = 'w'..'z'
10
+ @empty = []
11
+ end
12
+
13
+ describe "count" do
14
+ it "should default to `size' when no block is given" do
15
+ Enumerable.count(@hash).should == 2
16
+ end
17
+
18
+ it "should count items that satisfied block" do
19
+ Enumerable.count(@hash){ true }.should == @hash.size
20
+ Enumerable.count(@array){ false }.should == 0
21
+ Enumerable.count(@empty){ true }.should == @empty.size
22
+ Enumerable.count(@range){|c| c < 'z' }.should == 3
23
+ end
24
+ end
25
+
26
+ describe "sum" do
27
+ it "should append when no block is given" do
28
+ Enumerable.sum(@range).should == 'wxyz'
29
+ Enumerable.sum(@array).should == 'abcd'
30
+ Enumerable.sum(@empty).should == 0
31
+ end
32
+
33
+ it "should use block return value" do
34
+ Enumerable.sum(@range){ 100 }.should == 400
35
+ Enumerable.sum(@empty){ 100 }.should == 0
36
+ end
37
+ end
38
+
39
+ describe "group_by" do
40
+ it "should return a Hash" do
41
+ Enumerable.group_by(@array){ nil }.should be_a(Hash)
42
+ end
43
+
44
+ it "should collect elements into subcollections" do
45
+ Enumerable.group_by(@array){ :a }.should == { :a => @array }
46
+ Enumerable.group_by(@array){|x| x <= 'b'}.should == { true => %w(a b), false => %w(c d) }
47
+ Enumerable.group_by(@range){|x| x.to_i }.should == { 0 => %w(w x y z) }
48
+ Enumerable.group_by(@empty){ false }.should == {}
49
+ end
50
+ end
51
+
52
+ describe "index_by" do
53
+ it "should return a Hash" do
54
+ Enumerable.index_by(@array){ nil }.should be_a(Hash)
55
+ end
56
+
57
+ it "should collect only one element per group" do
58
+ Enumerable.index_by(@array){ nil }.should == { nil => 'd' }
59
+ Enumerable.index_by(@range){|x| x }.should == { 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z' }
60
+ end
61
+ end
62
+ end
63
+
64
+ end