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
@@ -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
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'spec_helper'
|
File without changes
|
@@ -1,28 +1,28 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
module Piggly
|
4
4
|
|
5
|
-
describe
|
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
|
17
|
+
describe Tags::ConditionalLoopTag do
|
18
18
|
end
|
19
19
|
|
20
|
-
describe
|
20
|
+
describe Tags::UnconditionalLoopTag do
|
21
21
|
before do
|
22
|
-
@tag =
|
22
|
+
@tag = Tags::UnconditionalLoopTag.new('for-loop')
|
23
23
|
end
|
24
24
|
|
25
|
-
it "
|
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
|
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
|