cascading.jruby 0.0.9 → 0.0.10
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.
- data/History.txt +15 -0
- data/lib/cascading/assembly.rb +138 -17
- data/lib/cascading/base.rb +0 -4
- data/lib/cascading/cascade.rb +25 -16
- data/lib/cascading/cascading.rb +25 -5
- data/lib/cascading/ext/array.rb +1 -7
- data/lib/cascading/flow.rb +18 -19
- data/lib/cascading/mode.rb +5 -1
- data/lib/cascading/operations.rb +11 -4
- data/lib/cascading/tap.rb +4 -0
- data/lib/cascading.rb +1 -5
- data/test/test_assembly.rb +135 -29
- data/test/test_cascade.rb +80 -0
- data/test/test_flow.rb +20 -0
- data/test/test_operations.rb +3 -2
- metadata +6 -76
- data/.travis.yml +0 -6
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -12
- data/HACKING.md +0 -23
- data/README.md +0 -9
- data/Rakefile +0 -46
- data/TODO +0 -13
- data/bin/make_job +0 -81
- data/ivy.xml +0 -25
- data/ivysettings.xml +0 -7
- data/samples/branch.rb +0 -30
- data/samples/copy.rb +0 -20
- data/samples/data/data2.txt +0 -88799
- data/samples/data/data_group_by.txt +0 -7
- data/samples/data/data_join1.txt +0 -3
- data/samples/data/data_join2.txt +0 -3
- data/samples/data/data_join3.txt +0 -3
- data/samples/data/genealogy/names/dist.all.last +0 -88799
- data/samples/data/gutenberg/the_outline_of_science_vol_1 +0 -12761
- data/samples/group_by.rb +0 -61
- data/samples/join.rb +0 -31
- data/samples/logwordcount.rb +0 -22
- data/samples/project.rb +0 -23
- data/samples/rename.rb +0 -20
- data/samples/scorenames.rb +0 -20
- data/samples/splitter.rb +0 -19
- data/samples/sub_assembly.rb +0 -30
- data/samples/union.rb +0 -36
- data/spec/cascading_spec.rb +0 -105
- data/spec/expr_spec.rb +0 -230
- data/spec/jruby_version_spec.rb +0 -72
- data/spec/resource/join_input.txt +0 -3
- data/spec/resource/test_input.txt +0 -4
- data/spec/scope_spec.rb +0 -149
- data/spec/spec.opts +0 -6
- data/spec/spec_helper.rb +0 -5
- data/spec/spec_util.rb +0 -92
- data/src/cascading/jruby/Main.java +0 -38
- data/src/cascading/jruby/runner.rb +0 -6
- data/tags +0 -342
- data/tasks/ann.rake +0 -80
- data/tasks/ant.rake +0 -23
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -206
- data/tasks/git.rake +0 -40
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -34
- data/tasks/rdoc.rake +0 -50
- data/tasks/rubyforge.rake +0 -55
- data/tasks/samples.rake +0 -19
- data/tasks/setup.rb +0 -300
- data/tasks/spec.rake +0 -59
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -42
- data/test/data/data1.txt +0 -14
- data/test/data/data2.txt +0 -14
- data/test/mock_assemblies.rb +0 -55
data/samples/group_by.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'group_by', :mode => :local do
|
7
|
-
flow 'group_by' do
|
8
|
-
source 'input', tap('samples/data/data_group_by.txt')
|
9
|
-
|
10
|
-
assembly 'input' do
|
11
|
-
split 'line', ['id', 'city'], :output => ['id', 'city']
|
12
|
-
|
13
|
-
branch 'group_by' do
|
14
|
-
group_by 'city', :sort_by => 'city' do
|
15
|
-
count
|
16
|
-
sum 'id', :type => :int
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
branch 'empty_group_by' do
|
21
|
-
group_by 'city', :sort_by => 'city' do
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
branch 'blockless_group_by' do
|
26
|
-
group_by 'city', :sort_by => 'city'
|
27
|
-
end
|
28
|
-
|
29
|
-
branch 'aggregate_by' do
|
30
|
-
group_by 'city' do
|
31
|
-
count
|
32
|
-
sum 'id', :type => :int
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# These compile into GroupBy unless we relax Aggregations#can_aggregate?
|
37
|
-
# to allow empty Aggregations#aggregate_bys, which does not make sense
|
38
|
-
#branch 'empty_aggregate_by' do
|
39
|
-
# group_by 'city' do
|
40
|
-
# end
|
41
|
-
#end
|
42
|
-
|
43
|
-
#branch 'blockless_aggregate_by' do
|
44
|
-
# group_by 'city'
|
45
|
-
#end
|
46
|
-
|
47
|
-
branch 'unique' do
|
48
|
-
sub_assembly Java::CascadingPipeAssembly::Unique.new(tail_pipe, fields('city'))
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
sink 'group_by', tap('output/group_by', :sink_mode => :replace)
|
53
|
-
sink 'empty_group_by', tap('output/empty_group_by', :sink_mode => :replace)
|
54
|
-
sink 'blockless_group_by', tap('output/blockless_group_by', :sink_mode => :replace)
|
55
|
-
sink 'aggregate_by', tap('output/aggregate_by', :sink_mode => :replace)
|
56
|
-
#sink 'empty_aggregate_by', tap('output/empty_aggregate_by', :sink_mode => :replace)
|
57
|
-
#sink 'blockless_aggregate_by', tap('output/blockless_aggregate_by', :sink_mode => :replace)
|
58
|
-
sink 'unique', tap('output/unique', :sink_mode => :replace)
|
59
|
-
end
|
60
|
-
#end.draw(ARGV[0])
|
61
|
-
end.complete
|
data/samples/join.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'join', :mode => :local do
|
7
|
-
flow 'join' do
|
8
|
-
source 'input1', tap('samples/data/data_join1.txt')
|
9
|
-
source 'input2', tap('samples/data/data_join2.txt')
|
10
|
-
source 'input3', tap('samples/data/data_join3.txt')
|
11
|
-
|
12
|
-
assembly 'input1' do
|
13
|
-
split 'line', ['id', 'name']
|
14
|
-
end
|
15
|
-
|
16
|
-
assembly 'input2' do
|
17
|
-
split 'line', ['id', 'age']
|
18
|
-
end
|
19
|
-
|
20
|
-
assembly 'input3' do
|
21
|
-
split 'line', ['id', 'city']
|
22
|
-
end
|
23
|
-
|
24
|
-
assembly 'join' do
|
25
|
-
join 'input1', 'input2', 'input3', :on => 'id'
|
26
|
-
project 'id', 'name', 'age', 'city'
|
27
|
-
end
|
28
|
-
|
29
|
-
sink 'join', tap('output/join', :sink_mode => :replace)
|
30
|
-
end
|
31
|
-
end.complete
|
data/samples/logwordcount.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'logwordcount', :mode => :local do
|
7
|
-
flow 'logwordcount' do
|
8
|
-
# This works just as well, but will get you blocked by Project Gutenberg
|
9
|
-
#source 'input', tap('http://www.gutenberg.org/files/20417/20417-8.txt')
|
10
|
-
source 'input', tap('samples/data/gutenberg/the_outline_of_science_vol_1')
|
11
|
-
|
12
|
-
assembly 'input' do
|
13
|
-
split_rows 'line', 'word', :pattern => /[.,]*\s+/, :output => 'word'
|
14
|
-
group_by 'word' do
|
15
|
-
count
|
16
|
-
end
|
17
|
-
group_by 'count', :reverse => true
|
18
|
-
end
|
19
|
-
|
20
|
-
sink 'input', tap('output/logwordcount', :sink_mode => :replace)
|
21
|
-
end
|
22
|
-
end.complete
|
data/samples/project.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
# History: "project" (verb) used to be known as "restrict"
|
5
|
-
|
6
|
-
require 'cascading'
|
7
|
-
|
8
|
-
cascade 'project', :mode => :local do
|
9
|
-
flow 'project' do
|
10
|
-
source 'input', tap('samples/data/data2.txt')
|
11
|
-
|
12
|
-
assembly 'input' do
|
13
|
-
split 'line', ['name', 'score1', 'score2', 'id'], :output => ['name', 'score1', 'score2', 'id']
|
14
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(4)
|
15
|
-
project 'name', 'score1', 'score2'
|
16
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(3)
|
17
|
-
project 'name', 'score2'
|
18
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(2)
|
19
|
-
end
|
20
|
-
|
21
|
-
sink 'input', tap('output/project', :sink_mode => :replace)
|
22
|
-
end
|
23
|
-
end.complete
|
data/samples/rename.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'rename', :mode => :local do
|
7
|
-
flow 'rename' do
|
8
|
-
source 'input', tap('samples/data/data2.txt')
|
9
|
-
|
10
|
-
assembly 'input' do
|
11
|
-
split 'line', ['name', 'score1', 'score2', 'id'], :output => ['name', 'score1', 'score2', 'id']
|
12
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(4)
|
13
|
-
rename 'name' => 'new_name', 'score1' => 'new_score1', 'score2' => 'new_score2'
|
14
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(4)
|
15
|
-
puts "Final field names: #{scope.values_fields.to_a.inspect}"
|
16
|
-
end
|
17
|
-
|
18
|
-
sink 'input', tap('output/rename', :sink_mode => :replace)
|
19
|
-
end
|
20
|
-
end.complete
|
data/samples/scorenames.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'scorenames', :mode => :local do
|
7
|
-
flow 'scorenames' do
|
8
|
-
# You don't have to curl and cache inputs: tap can fetch via HTTP
|
9
|
-
#source 'input', tap('http://www.census.gov/genealogy/names/dist.all.last')
|
10
|
-
source 'input', tap('samples/data/genealogy/names/dist.all.last')
|
11
|
-
|
12
|
-
assembly 'input' do
|
13
|
-
split 'line', ['name', 'val1', 'val2', 'id']
|
14
|
-
insert 'val3' => expr('val2:double < 40.0 ? val1:double : val2:double')
|
15
|
-
project 'name', 'val3', 'id'
|
16
|
-
end
|
17
|
-
|
18
|
-
sink 'input', tap('output/scorenames', :sink_mode => :replace)
|
19
|
-
end
|
20
|
-
end.complete
|
data/samples/splitter.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'splitter', :mode => :local do
|
7
|
-
flow 'splitter' do
|
8
|
-
source 'input', tap('samples/data/data2.txt')
|
9
|
-
|
10
|
-
assembly 'input' do
|
11
|
-
split 'line', ['name', 'score1', 'score2', 'id'], :output => ['name', 'score1', 'score2', 'id']
|
12
|
-
group_by 'score1' do
|
13
|
-
count
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
sink 'input', tap('output/splitter', :sink_mode => :replace)
|
18
|
-
end
|
19
|
-
end.complete
|
data/samples/sub_assembly.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'sub_assembly', :mode => :local do
|
7
|
-
flow 'sub_assembly' do
|
8
|
-
source 'input', tap('samples/data/data2.txt')
|
9
|
-
|
10
|
-
assembly 'input' do
|
11
|
-
split 'line', ['name', 'score1', 'score2', 'id'], :output => ['name', 'score1', 'score2', 'id']
|
12
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(4)
|
13
|
-
sub_assembly Java::CascadingPipeAssembly::Discard.new(tail_pipe, fields('id'))
|
14
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(3)
|
15
|
-
|
16
|
-
sub_assembly Java::CascadingPipeAssembly::Unique.new(tail_pipe, fields('name'))
|
17
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(3)
|
18
|
-
|
19
|
-
sub_assembly Java::CascadingPipeAssembly::Retain.new(tail_pipe, fields(['score1', 'score2']))
|
20
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(2)
|
21
|
-
|
22
|
-
sub_assembly Java::CascadingPipeAssembly::Rename.new(tail_pipe, fields(['score1', 'score2']), fields(['score_a', 'score_b']))
|
23
|
-
assert Java::CascadingOperationAssertion::AssertSizeEquals.new(2)
|
24
|
-
|
25
|
-
debug_scope
|
26
|
-
end
|
27
|
-
|
28
|
-
sink 'input', tap('output/sub_assembly', :sink_mode => :replace)
|
29
|
-
end
|
30
|
-
end.complete
|
data/samples/union.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
#! /usr/bin/env jruby
|
2
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
-
|
4
|
-
require 'cascading'
|
5
|
-
|
6
|
-
cascade 'union', :mode => :local do
|
7
|
-
flow 'union' do
|
8
|
-
# You don't have to curl and cache inputs: tap can fetch via HTTP
|
9
|
-
#source 'input', tap('http://www.census.gov/genealogy/names/dist.all.last')
|
10
|
-
source 'input', tap('samples/data/genealogy/names/dist.all.last')
|
11
|
-
|
12
|
-
assembly 'input' do
|
13
|
-
split 'line', ['name', 'score1', 'score2', 'id']
|
14
|
-
|
15
|
-
branch 'branch1' do
|
16
|
-
group_by 'score1', 'name' do
|
17
|
-
count
|
18
|
-
end
|
19
|
-
rename 'score1' => 'score'
|
20
|
-
end
|
21
|
-
|
22
|
-
branch 'branch2' do
|
23
|
-
group_by 'score2', 'name' do
|
24
|
-
count
|
25
|
-
end
|
26
|
-
rename 'score2' => 'score'
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
assembly 'union' do
|
31
|
-
union 'branch1', 'branch2'
|
32
|
-
end
|
33
|
-
|
34
|
-
sink 'union', tap('output/union', :sink_mode => :replace)
|
35
|
-
end
|
36
|
-
end.complete
|
data/spec/cascading_spec.rb
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
context Cascading do
|
4
|
-
it 'should handle string and integer field names' do
|
5
|
-
f = fields(['a', 1, 'b', 2])
|
6
|
-
f.to_a.should == ['a', 1, 'b', 2]
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'should dedup field names from multiple sources' do
|
10
|
-
left_names = ['a', 'b', 'c', 'd', 'e']
|
11
|
-
mid_names = ['a', 'f']
|
12
|
-
right_names = ['a', 'g']
|
13
|
-
|
14
|
-
field_names = dedup_field_names(left_names, mid_names, right_names)
|
15
|
-
field_names.should == [
|
16
|
-
'a', 'b', 'c', 'd', 'e',
|
17
|
-
'a_', 'f',
|
18
|
-
'a__', 'g'
|
19
|
-
]
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should fail to resolve duplicate fields' do
|
23
|
-
incoming = fields(['line'])
|
24
|
-
declared = fields(['line'])
|
25
|
-
outgoing = all_fields
|
26
|
-
lambda do
|
27
|
-
begin
|
28
|
-
resolved = Java::CascadingTuple::Fields.resolve(outgoing, [incoming, declared].to_java(Java::CascadingTuple::Fields))
|
29
|
-
rescue NativeException => e
|
30
|
-
raise e.cause
|
31
|
-
end
|
32
|
-
end.should raise_error Java::CascadingTuple::TupleException, 'field name already exists: line'
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'should find branches to sink' do
|
36
|
-
cascade 'branched_pass', :mode => :local do
|
37
|
-
flow 'branched_pass' do
|
38
|
-
source 'input', tap('spec/resource/test_input.txt', :scheme => text_line_scheme)
|
39
|
-
assembly 'input' do
|
40
|
-
branch 'branched_input' do
|
41
|
-
project 'line'
|
42
|
-
end
|
43
|
-
end
|
44
|
-
sink 'branched_input', tap("#{OUTPUT_DIR}/branched_pass_out", :sink_mode => :replace)
|
45
|
-
end
|
46
|
-
end.complete
|
47
|
-
|
48
|
-
ilc = `wc -l spec/resource/test_input.txt`.strip.split(/\s+/).first
|
49
|
-
olc = `wc -l #{OUTPUT_DIR}/branched_pass_out`.strip.split(/\s+/).first
|
50
|
-
olc.should == ilc
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should create an isolated namespace per cascade' do
|
54
|
-
cascade 'double', :mode => :local do
|
55
|
-
flow 'double' do
|
56
|
-
source 'input', tap('spec/resource/test_input.txt', :scheme => text_line_scheme)
|
57
|
-
assembly 'input' do # Dup name
|
58
|
-
insert 'doubled' => expr('line:string + "," + line:string')
|
59
|
-
project 'doubled'
|
60
|
-
end
|
61
|
-
sink 'input', tap("#{OUTPUT_DIR}/double_out", :sink_mode => :replace)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
cascade 'pass', :mode => :local do
|
66
|
-
flow 'pass' do
|
67
|
-
source 'input', tap('spec/resource/test_input.txt', :scheme => text_line_scheme)
|
68
|
-
assembly 'input' do # Dup name
|
69
|
-
project 'line'
|
70
|
-
end
|
71
|
-
sink 'input', tap("#{OUTPUT_DIR}/pass_out", :sink_mode => :replace)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
Cascade.get('double').complete
|
76
|
-
Cascade.get('pass').complete
|
77
|
-
diff = `diff #{OUTPUT_DIR}/double_out #{OUTPUT_DIR}/pass_out`
|
78
|
-
diff.should_not be_empty
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'should support joins in branches' do
|
82
|
-
cascade 'branch_join', :mode => :local do
|
83
|
-
flow 'branch_join' do
|
84
|
-
source 'left', tap('spec/resource/join_input.txt', :scheme => text_line_scheme)
|
85
|
-
source 'right', tap('spec/resource/join_input.txt', :scheme => text_line_scheme)
|
86
|
-
|
87
|
-
assembly 'left' do
|
88
|
-
split 'line', ['x', 'y', 'z'], :pattern => /,/
|
89
|
-
project 'x', 'y', 'z'
|
90
|
-
end
|
91
|
-
|
92
|
-
assembly 'right' do
|
93
|
-
split 'line', ['x', 'y', 'z'], :pattern => /,/
|
94
|
-
project 'x', 'y', 'z'
|
95
|
-
|
96
|
-
branch 'branch_join' do
|
97
|
-
join 'left', 'right', :on => 'x'
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
sink 'branch_join', tap("#{OUTPUT_DIR}/branch_join_out.txt", :sink_mode => :replace)
|
102
|
-
end
|
103
|
-
end.complete
|
104
|
-
end
|
105
|
-
end
|
data/spec/expr_spec.rb
DELETED
@@ -1,230 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
context ExprStub do
|
4
|
-
it 'should allow expr syntax' do
|
5
|
-
test_assembly do
|
6
|
-
insert 'foo' => 1, 'bar' => expr('offset:int')
|
7
|
-
check_scope :values_fields => ['offset', 'line', 'bar', 'foo']
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'should compile expressions' do
|
12
|
-
e = ExprStub.new('x:int + y:int')
|
13
|
-
e.compile
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'should throw an exception for parsing failures' do
|
17
|
-
e = ExprStub.new('x:int + doesnotparse y:string')
|
18
|
-
lambda{ e.compile }.should raise_error CascadingException
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'should throw an exception for compile failures' do
|
22
|
-
e = ExprStub.new('new DoesNotExist(x:int).doesnotcompile()')
|
23
|
-
lambda{ e.compile }.should raise_error CascadingException
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should throw an exception for compile failures' do
|
27
|
-
e = ExprStub.new('true ? x:int : y:string')
|
28
|
-
lambda{ e.compile }.should raise_error CascadingException
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'should evaluate expressions' do
|
32
|
-
e = ExprStub.new('x:int + y:int')
|
33
|
-
result = e.eval(:x => 2, :y => 3)
|
34
|
-
result.should == 5
|
35
|
-
|
36
|
-
e = ExprStub.new('x:int + y:string')
|
37
|
-
result = e.eval(:x => 2, :y => 'blah')
|
38
|
-
result.should == '2blah'
|
39
|
-
|
40
|
-
e = ExprStub.new('x:long + y:int')
|
41
|
-
result = e.eval(:x => 2, :y => 3)
|
42
|
-
result.should == 5
|
43
|
-
|
44
|
-
e = ExprStub.new('x:double + y:int')
|
45
|
-
result = e.eval(:x => 2.0, :y => 3)
|
46
|
-
result.should == 5.0
|
47
|
-
|
48
|
-
e = ExprStub.new('x:float + y:int')
|
49
|
-
result = e.eval(:x => 2.0, :y => 3)
|
50
|
-
result.should == 5.0
|
51
|
-
|
52
|
-
e = ExprStub.new('x:bool && y:bool')
|
53
|
-
result = e.eval(:x => true, :y => false)
|
54
|
-
result.should == false
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should evaluate expressions despite argument order' do
|
58
|
-
e = ExprStub.new('x:int + y:int')
|
59
|
-
result = e.eval(:y => 3, :x => 2)
|
60
|
-
result.should == 5
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'should throw an exception for invalid actual arguments' do
|
64
|
-
e = ExprStub.new('x:int + y:int')
|
65
|
-
lambda{ e.eval(:x => 2, :y => 'blah') }.should raise_error CascadingException
|
66
|
-
|
67
|
-
# Janino does not coerce numeric strings to Java Integers
|
68
|
-
e = ExprStub.new('x:int + y:int')
|
69
|
-
lambda{ e.eval(:x => 2, :y => '3') }.should raise_error CascadingException
|
70
|
-
|
71
|
-
# eval should not coerce numeric strings to Java Floats
|
72
|
-
e = ExprStub.new('x:int + y:float')
|
73
|
-
lambda{ e.eval(:x => 2, :y => '3') }.should raise_error CascadingException
|
74
|
-
|
75
|
-
# eval should not coerce numeric strings to Java Longs
|
76
|
-
e = ExprStub.new('x:long + y:int')
|
77
|
-
lambda{ e.eval(:x => '2', :y => 3) }.should raise_error CascadingException
|
78
|
-
|
79
|
-
# eval should not coerce floats to Java Longs
|
80
|
-
e = ExprStub.new('x:long + y:int')
|
81
|
-
lambda{ e.eval(:x => 2.0, :y => 3) }.should raise_error CascadingException
|
82
|
-
|
83
|
-
# eval should not coerce integers to Java Floats
|
84
|
-
e = ExprStub.new('x:int + y:float')
|
85
|
-
lambda{ e.eval(:x => 2, :y => 3) }.should raise_error CascadingException
|
86
|
-
|
87
|
-
e = ExprStub.new('x:float + y:int')
|
88
|
-
lambda{ e.eval(:x => 'blah', :y => 3) }.should raise_error CascadingException
|
89
|
-
|
90
|
-
e = ExprStub.new('x:long + y:int')
|
91
|
-
lambda{ e.eval(:x => [], :y => 3) }.should raise_error CascadingException
|
92
|
-
|
93
|
-
e = ExprStub.new('x:long + y:int')
|
94
|
-
lambda{ e.eval(:x => nil, :y => 3) }.should raise_error CascadingException
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'should throw an exception for missing actual arguments' do
|
98
|
-
e = ExprStub.new('x:int + y:int')
|
99
|
-
lambda{ e.eval(:x => 2) }.should raise_error ExprArgException
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'should ignore extraneous actual arguments' do
|
103
|
-
e = ExprStub.new('x:int + y:int')
|
104
|
-
result = e.eval(:x => 2, :y => 3, :z => 'unused')
|
105
|
-
result.should == 5
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'should use default actual arguments to validate' do
|
109
|
-
e = ExprStub.new('x:int + y:int')
|
110
|
-
result = e.validate
|
111
|
-
result.should == 0
|
112
|
-
|
113
|
-
e = ExprStub.new('x:long + y:int')
|
114
|
-
result = e.validate
|
115
|
-
result.should == 0
|
116
|
-
|
117
|
-
e = ExprStub.new('x:double + y:int')
|
118
|
-
result = e.validate
|
119
|
-
result.should == 0.0
|
120
|
-
|
121
|
-
e = ExprStub.new('x:float + y:int')
|
122
|
-
result = e.validate
|
123
|
-
result.should == 0.0
|
124
|
-
|
125
|
-
e = ExprStub.new('x:bool && y:bool')
|
126
|
-
result = e.validate
|
127
|
-
result.should == false
|
128
|
-
|
129
|
-
e = ExprStub.new('x:int + y:string')
|
130
|
-
result = e.validate
|
131
|
-
result.should == '0null'
|
132
|
-
|
133
|
-
e = ExprStub.new('x:string + y:string')
|
134
|
-
result = e.validate
|
135
|
-
result.should == 'nullnull'
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'should fail to validate these expressions with default actual arguments' do
|
139
|
-
e = ExprStub.new('x:string.indexOf("R") == -1')
|
140
|
-
lambda { e.validate }.should raise_error CascadingException
|
141
|
-
|
142
|
-
e = ExprStub.new('x:string.substring(0, 8)')
|
143
|
-
lambda { e.validate }.should raise_error CascadingException
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'should allow overriding default actual arguments for validation' do
|
147
|
-
e = ExprStub.new('x:string.indexOf("R") == -1')
|
148
|
-
result = e.validate(:x => 'nothinghere')
|
149
|
-
result.should == true
|
150
|
-
|
151
|
-
e = ExprStub.new('x:string.substring(0, 8)')
|
152
|
-
result = e.validate(:x => 'atleast8chars')
|
153
|
-
result.should == 'atleast8'
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'should allow overriding default actual arguments for validation via expr' do
|
157
|
-
expr('x:string.indexOf("R") == -1', :validate_with => { :x => 'nothinghere' })
|
158
|
-
expr('x:string.substring(0, 8)', :validate_with => { :x => 'atleast8chars' })
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'should allow overriding default actual arguments for validation via filter' do
|
162
|
-
test_assembly do
|
163
|
-
filter :expression => 'line:string.indexOf("R") == -1', :validate_with => { :line => 'nothinghere' }
|
164
|
-
check_scope :values_fields => ['offset', 'line']
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
it 'should allow overriding default actual arguments for validation via where' do
|
169
|
-
test_assembly do
|
170
|
-
where 'line:string.equals("not_set") && "0".equals(offset:string)', :validate_with => { :line => 'nulls_rejected' }
|
171
|
-
check_scope :values_fields => ['offset', 'line']
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'should allow disabling validation via expr' do
|
176
|
-
expr('x:string.indexOf("R") == -1', :validate => false)
|
177
|
-
expr('x:string.substring(0, 8)', :validate => false)
|
178
|
-
end
|
179
|
-
|
180
|
-
it 'should allow disabling validation via filter' do
|
181
|
-
test_assembly do
|
182
|
-
filter :expression => 'line:string.indexOf("R") == -1', :validate => false
|
183
|
-
check_scope :values_fields => ['offset', 'line']
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
it 'should allow disabling validation via where' do
|
188
|
-
test_assembly do
|
189
|
-
where 'line:string.indexOf("R") == -1', :validate => false
|
190
|
-
check_scope :values_fields => ['offset', 'line']
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
it 'should only allow floating point division by zero' do
|
195
|
-
e = ExprStub.new('x:float / y:float')
|
196
|
-
result = e.validate
|
197
|
-
result.nan?.should == true
|
198
|
-
|
199
|
-
e = ExprStub.new('x:double / y:double')
|
200
|
-
result = e.validate
|
201
|
-
result.nan?.should == true
|
202
|
-
|
203
|
-
# From: http://download.oracle.com/javase/6/docs/api/java/lang/ArithmeticException.html
|
204
|
-
# Thrown when an exceptional arithmetic condition has occurred. For
|
205
|
-
# example, an integer "divide by zero" throws an instance of this class.
|
206
|
-
|
207
|
-
e = ExprStub.new('x:long / y:long')
|
208
|
-
lambda { e.validate }.should raise_error CascadingException
|
209
|
-
|
210
|
-
e = ExprStub.new('x:int / y:int')
|
211
|
-
lambda { e.validate }.should raise_error CascadingException
|
212
|
-
end
|
213
|
-
|
214
|
-
it 'should catch missing fields in filter expressions' do
|
215
|
-
lambda do
|
216
|
-
test_assembly do
|
217
|
-
filter :expression => 'doesnotexist:int > offset:int'
|
218
|
-
check_scope :values_fields => ['offset', 'line', 'bar', 'foo']
|
219
|
-
end
|
220
|
-
end.should raise_error ExprArgException
|
221
|
-
end
|
222
|
-
|
223
|
-
it 'should catch missing fields in insert expressions' do
|
224
|
-
lambda do
|
225
|
-
test_assembly do
|
226
|
-
insert 'foo' => 1, 'bar' => expr('doesnotexist:int + offset:int')
|
227
|
-
end
|
228
|
-
end.should raise_error ExprArgException
|
229
|
-
end
|
230
|
-
end
|
data/spec/jruby_version_spec.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
context Object do
|
4
|
-
it 'should definitely not do this' do
|
5
|
-
names = ['x', 'y'].to_java(java.lang.String)
|
6
|
-
types = [java.lang.Integer.java_class, java.lang.Integer.java_class].to_java(java.lang.Class)
|
7
|
-
evaluator = Java::OrgCodehausJanino::ExpressionEvaluator.new('x + y', java.lang.Comparable.java_class, names, types)
|
8
|
-
|
9
|
-
thrown = nil
|
10
|
-
exception = nil
|
11
|
-
begin
|
12
|
-
evaluator.evaluate([nil, nil].to_java)
|
13
|
-
rescue java.lang.IllegalArgumentException => iae
|
14
|
-
thrown = 'IllegalArgumentException'
|
15
|
-
exception = iae
|
16
|
-
rescue java.lang.reflect.InvocationTargetException => ite
|
17
|
-
thrown = 'InvocationTargetException'
|
18
|
-
exception = ite
|
19
|
-
end
|
20
|
-
|
21
|
-
# How can this be? A nil exception?
|
22
|
-
thrown.should == 'InvocationTargetException'
|
23
|
-
exception.should be_nil
|
24
|
-
end
|
25
|
-
|
26
|
-
case JRUBY_VERSION
|
27
|
-
when '1.2.0'
|
28
|
-
it 'should handle Fixnum -> Long for ExprStub#eval' do
|
29
|
-
e = ExprStub.new('x:long + y:long')
|
30
|
-
result = e.eval(:x => 2, :y => 3)
|
31
|
-
result.should == 5
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should handle Fixnum -> Long for ExprStub#validate' do
|
35
|
-
e = ExprStub.new('x:long + y:long')
|
36
|
-
result = e.validate
|
37
|
-
result.should == 0
|
38
|
-
end
|
39
|
-
when '1.4.0'
|
40
|
-
# This test previously failed for 1.4.0 (it's duplicated in cascading_spec)
|
41
|
-
it 'should handle string and integer field names' do
|
42
|
-
f = fields(['a', 1, 'b', 2])
|
43
|
-
f.to_a.should == ['a', 1, 'b', 2]
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should handle Fixnum -> Integer for ExprStub#eval' do
|
47
|
-
e = ExprStub.new('x:int + y:int')
|
48
|
-
result = e.eval(:x => 2, :y => 3)
|
49
|
-
result.should == 5
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should handle Fixnum -> Integer for ExprStub#validate' do
|
53
|
-
e = ExprStub.new('x:int + y:int')
|
54
|
-
result = e.validate
|
55
|
-
result.should == 0
|
56
|
-
end
|
57
|
-
when '1.5.3', '1.6.5'
|
58
|
-
it 'should handle Fixnum -> Integer for ExprStub#eval' do
|
59
|
-
e = ExprStub.new('x:int + y:int')
|
60
|
-
result = e.eval(:x => 2, :y => 3)
|
61
|
-
result.should == 5
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should handle Fixnum -> Integer for ExprStub#validate' do
|
65
|
-
e = ExprStub.new('x:int + y:int')
|
66
|
-
result = e.validate
|
67
|
-
result.should == 0
|
68
|
-
end
|
69
|
-
else
|
70
|
-
raise "cascading.jruby has not been tested with JRuby version #{JRUBY_VERSION}"
|
71
|
-
end
|
72
|
-
end
|