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
@@ -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