pacer 0.9.1.1-java
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/.autotest +8 -0
- data/.document +5 -0
- data/.gitignore +26 -0
- data/.rspec +1 -0
- data/.rvmrc +0 -0
- data/CONTRIBUTORS +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +24 -0
- data/README.md +187 -0
- data/Rakefile +49 -0
- data/autotest/discover.rb +1 -0
- data/bin/autospec +16 -0
- data/bin/autotest +16 -0
- data/bin/rake +16 -0
- data/bin/rcov +16 -0
- data/bin/rspec +16 -0
- data/bin/yard +16 -0
- data/bin/yardoc +16 -0
- data/lib/pacer/blueprints/extensions.rb +77 -0
- data/lib/pacer/blueprints/multi_graph.rb +121 -0
- data/lib/pacer/blueprints/ruby_graph.rb +199 -0
- data/lib/pacer/blueprints/tg.rb +100 -0
- data/lib/pacer/blueprints.rb +4 -0
- data/lib/pacer/core/graph/edges_route.rb +92 -0
- data/lib/pacer/core/graph/element_route.rb +171 -0
- data/lib/pacer/core/graph/graph_index_route.rb +48 -0
- data/lib/pacer/core/graph/graph_route.rb +55 -0
- data/lib/pacer/core/graph/mixed_route.rb +96 -0
- data/lib/pacer/core/graph/vertices_route.rb +220 -0
- data/lib/pacer/core/graph.rb +13 -0
- data/lib/pacer/core/route.rb +502 -0
- data/lib/pacer/core/side_effect.rb +11 -0
- data/lib/pacer/core.rb +8 -0
- data/lib/pacer/exceptions.rb +11 -0
- data/lib/pacer/extensions/block_filter_element.rb +22 -0
- data/lib/pacer/extensions.rb +6 -0
- data/lib/pacer/filter/block_filter.rb +31 -0
- data/lib/pacer/filter/collection_filter.rb +109 -0
- data/lib/pacer/filter/empty_filter.rb +70 -0
- data/lib/pacer/filter/future_filter.rb +68 -0
- data/lib/pacer/filter/index_filter.rb +30 -0
- data/lib/pacer/filter/loop_filter.rb +95 -0
- data/lib/pacer/filter/object_filter.rb +55 -0
- data/lib/pacer/filter/property_filter/edge_filters.rb +93 -0
- data/lib/pacer/filter/property_filter/filters.rb +269 -0
- data/lib/pacer/filter/property_filter.rb +111 -0
- data/lib/pacer/filter/random_filter.rb +13 -0
- data/lib/pacer/filter/range_filter.rb +104 -0
- data/lib/pacer/filter/uniq_filter.rb +12 -0
- data/lib/pacer/filter/where_filter/node_visitor.rb +280 -0
- data/lib/pacer/filter/where_filter.rb +47 -0
- data/lib/pacer/filter.rb +17 -0
- data/lib/pacer/function_resolver.rb +43 -0
- data/lib/pacer/graph/edge_mixin.rb +127 -0
- data/lib/pacer/graph/element_mixin.rb +202 -0
- data/lib/pacer/graph/graph_indices_mixin.rb +93 -0
- data/lib/pacer/graph/graph_mixin.rb +361 -0
- data/lib/pacer/graph/graph_transactions_mixin.rb +207 -0
- data/lib/pacer/graph/index_mixin.rb +30 -0
- data/lib/pacer/graph/vertex_mixin.rb +119 -0
- data/lib/pacer/graph.rb +14 -0
- data/lib/pacer/pipe/blackbox_pipeline.rb +48 -0
- data/lib/pacer/pipe/block_filter_pipe.rb +38 -0
- data/lib/pacer/pipe/collection_filter_pipe.rb +10 -0
- data/lib/pacer/pipe/cross_product_transform_pipe.rb +48 -0
- data/lib/pacer/pipe/enumerable_pipe.rb +30 -0
- data/lib/pacer/pipe/expandable_pipe.rb +63 -0
- data/lib/pacer/pipe/id_collection_filter_pipe.rb +33 -0
- data/lib/pacer/pipe/is_empty_pipe.rb +30 -0
- data/lib/pacer/pipe/is_unique_pipe.rb +61 -0
- data/lib/pacer/pipe/label_collection_filter_pipe.rb +21 -0
- data/lib/pacer/pipe/label_prefix_pipe.rb +21 -0
- data/lib/pacer/pipe/loop_pipe.rb +86 -0
- data/lib/pacer/pipe/map_pipe.rb +36 -0
- data/lib/pacer/pipe/never_pipe.rb +9 -0
- data/lib/pacer/pipe/process_pipe.rb +37 -0
- data/lib/pacer/pipe/property_comparison_pipe.rb +40 -0
- data/lib/pacer/pipe/ruby_pipe.rb +25 -0
- data/lib/pacer/pipe/simple_visitor_pipe.rb +43 -0
- data/lib/pacer/pipe/stream_sort_pipe.rb +84 -0
- data/lib/pacer/pipe/stream_uniq_pipe.rb +33 -0
- data/lib/pacer/pipe/type_filter_pipe.rb +22 -0
- data/lib/pacer/pipe/unary_transform_pipe.rb +59 -0
- data/lib/pacer/pipe/variable_store_iterator_wrapper.rb +26 -0
- data/lib/pacer/pipe/visitor_pipe.rb +67 -0
- data/lib/pacer/pipes.rb +61 -0
- data/lib/pacer/route/mixin/bulk_operations.rb +52 -0
- data/lib/pacer/route/mixin/route_operations.rb +107 -0
- data/lib/pacer/route/mixin/variable_route_module.rb +26 -0
- data/lib/pacer/route/mixins.rb +3 -0
- data/lib/pacer/route.rb +228 -0
- data/lib/pacer/routes.rb +6 -0
- data/lib/pacer/side_effect/aggregate.rb +31 -0
- data/lib/pacer/side_effect/counted.rb +30 -0
- data/lib/pacer/side_effect/group_count.rb +44 -0
- data/lib/pacer/side_effect/is_unique.rb +32 -0
- data/lib/pacer/side_effect/section.rb +25 -0
- data/lib/pacer/side_effect/visitor.rb +37 -0
- data/lib/pacer/side_effect.rb +11 -0
- data/lib/pacer/support/array_list.rb +28 -0
- data/lib/pacer/support/enumerable.rb +100 -0
- data/lib/pacer/support/hash.rb +9 -0
- data/lib/pacer/support/iterator_mixins.rb +110 -0
- data/lib/pacer/support/native_exception.rb +22 -0
- data/lib/pacer/support/proc.rb +16 -0
- data/lib/pacer/support.rb +10 -0
- data/lib/pacer/transform/cap.rb +50 -0
- data/lib/pacer/transform/gather.rb +9 -0
- data/lib/pacer/transform/has_count_cap.rb +41 -0
- data/lib/pacer/transform/join.rb +181 -0
- data/lib/pacer/transform/map.rb +23 -0
- data/lib/pacer/transform/path.rb +50 -0
- data/lib/pacer/transform/process.rb +23 -0
- data/lib/pacer/transform/scatter.rb +23 -0
- data/lib/pacer/transform/sort_section.rb +103 -0
- data/lib/pacer/transform/stream_sort.rb +21 -0
- data/lib/pacer/transform/stream_uniq.rb +21 -0
- data/lib/pacer/transform.rb +16 -0
- data/lib/pacer/utils/graph_analysis.rb +112 -0
- data/lib/pacer/utils/trie.rb +93 -0
- data/lib/pacer/utils/tsort.rb +65 -0
- data/lib/pacer/utils/y_files.rb +127 -0
- data/lib/pacer/utils.rb +10 -0
- data/lib/pacer/version.rb +13 -0
- data/lib/pacer/wrappers/edge_wrapper.rb +51 -0
- data/lib/pacer/wrappers/element_wrapper.rb +78 -0
- data/lib/pacer/wrappers/new_element.rb +106 -0
- data/lib/pacer/wrappers/vertex_wrapper.rb +51 -0
- data/lib/pacer/wrappers.rb +19 -0
- data/lib/pacer-0.9.1.1-standalone.jar +0 -0
- data/lib/pacer.rb +290 -0
- data/pacer.gemspec +30 -0
- data/pom/standalone.xml +22 -0
- data/pom.xml +124 -0
- data/samples/grateful-dead.xml +26380 -0
- data/samples/grateful_dead.rb +63 -0
- data/samples/profile.rb +15 -0
- data/spec/data/grateful-dead.xml +26380 -0
- data/spec/data/pacer.graphml +319 -0
- data/spec/pacer/blueprints/dex_spec.rb +172 -0
- data/spec/pacer/blueprints/neo4j_spec.rb +177 -0
- data/spec/pacer/blueprints/tg_spec.rb +128 -0
- data/spec/pacer/core/graph/edges_route_spec.rb +52 -0
- data/spec/pacer/core/graph/element_route_spec.rb +46 -0
- data/spec/pacer/core/graph/graph_route_spec.rb +94 -0
- data/spec/pacer/core/graph/vertices_route_spec.rb +169 -0
- data/spec/pacer/core/route_spec.rb +197 -0
- data/spec/pacer/filter/collection_filter_spec.rb +19 -0
- data/spec/pacer/filter/empty_filter_spec.rb +29 -0
- data/spec/pacer/filter/future_filter_spec.rb +97 -0
- data/spec/pacer/filter/loop_filter_spec.rb +31 -0
- data/spec/pacer/filter/property_filter_spec.rb +111 -0
- data/spec/pacer/filter/random_filter_spec.rb +17 -0
- data/spec/pacer/filter/uniq_filter_spec.rb +18 -0
- data/spec/pacer/filter/where_filter_spec.rb +93 -0
- data/spec/pacer/graph/edge_mixin_spec.rb +116 -0
- data/spec/pacer/graph/element_mixin_spec.rb +297 -0
- data/spec/pacer/graph/graph_mixin_spec.rb +538 -0
- data/spec/pacer/graph/index_mixin_spec.rb +0 -0
- data/spec/pacer/graph/vertex_mixin_spec.rb +192 -0
- data/spec/pacer/pipe/block_filter_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/labels_filter_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/ruby_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/type_filter_pipe_spec.rb +0 -0
- data/spec/pacer/route/mixin/base_spec.rb +419 -0
- data/spec/pacer/route/mixin/bulk_operations_spec.rb +30 -0
- data/spec/pacer/route/mixin/route_operations_spec.rb +127 -0
- data/spec/pacer/support/array_list_spec.rb +0 -0
- data/spec/pacer/support/enumerable_spec.rb +115 -0
- data/spec/pacer/transform/join_spec.rb +138 -0
- data/spec/pacer/transform/path_spec.rb +54 -0
- data/spec/pacer/utils/tsort_spec.rb +89 -0
- data/spec/pacer/wrapper/edge_wrapper_spec.rb +33 -0
- data/spec/pacer/wrapper/element_wrapper_spec.rb +169 -0
- data/spec/pacer/wrapper/vertex_wrapper_spec.rb +33 -0
- data/spec/pacer_spec.rb +0 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/support/contexts.rb +14 -0
- data/spec/support/graph_runner.rb +142 -0
- data/spec/support/matchers.rb +19 -0
- data/spec/support/use_transactions.rb +31 -0
- data/spec/tackle/simple_mixin.rb +21 -0
- data/spec/tackle/tinkerpop_graph_mixins.rb +60 -0
- metadata +364 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# New tests:
|
|
4
|
+
Run.tg(:read_only) do
|
|
5
|
+
use_pacer_graphml_data(:read_only)
|
|
6
|
+
|
|
7
|
+
describe RouteOperations do
|
|
8
|
+
describe '#most_frequent' do
|
|
9
|
+
context '()' do
|
|
10
|
+
subject { graph.v[:type].most_frequent }
|
|
11
|
+
it { should == 'project' }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context '(0)' do
|
|
15
|
+
subject { graph.v[:type].most_frequent(0) }
|
|
16
|
+
it { should == 'project' }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context '(1)' do
|
|
20
|
+
subject { graph.v[:type].most_frequent(1) }
|
|
21
|
+
it { should == 'person' }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context '(0..1)' do
|
|
25
|
+
subject { graph.v[:type].most_frequent(0..1) }
|
|
26
|
+
it { should be_a Pacer::Core::Route }
|
|
27
|
+
its(:element_type) { should == Object }
|
|
28
|
+
its(:to_a) { should == ['project', 'person'] }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context '(0, true)' do
|
|
32
|
+
subject { graph.v[:type].most_frequent(0, true) }
|
|
33
|
+
it { should == ['project', 4] }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context '(1, true)' do
|
|
37
|
+
subject { graph.v[:type].most_frequent(1, true) }
|
|
38
|
+
it { should == ['person', 2] }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context '(0..1, true)' do
|
|
42
|
+
subject { graph.v[:type].most_frequent(0..1, true) }
|
|
43
|
+
it { should == [['project', 4], ['person', 2]] }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
Run.tg do
|
|
50
|
+
use_pacer_graphml_data
|
|
51
|
+
|
|
52
|
+
describe RouteOperations do
|
|
53
|
+
before do
|
|
54
|
+
setup_data
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#build_index' do
|
|
58
|
+
context "('new_index', 'k') { count += 1 }", :transactions => true do
|
|
59
|
+
it 'should build the index with raw elements' do
|
|
60
|
+
count = 0
|
|
61
|
+
index = graph.v.build_index('new_index', 'k', 'name')
|
|
62
|
+
index.should_not be_nil
|
|
63
|
+
index.get('k', 'pangloss').count.should == 1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should build the index with wrapped elements' do
|
|
67
|
+
count = 0
|
|
68
|
+
index = graph.v(TP::Person).build_index('new_index', 'k', 'name')
|
|
69
|
+
index.should_not be_nil
|
|
70
|
+
index.get('k', 'pangloss').count.should == 1
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'should do nothing if there are no elements' do
|
|
74
|
+
count = 0
|
|
75
|
+
index = graph.v.limit(0).build_index('new_index', 'k', 'name')
|
|
76
|
+
index.should be_nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
after do
|
|
80
|
+
graph.dropIndex 'new_index'
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Modernize these old tests:
|
|
89
|
+
describe RouteOperations do
|
|
90
|
+
before :all do
|
|
91
|
+
@g = Pacer.tg 'spec/data/pacer.graphml'
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe '#as' do
|
|
95
|
+
it 'should set the variable to the correct node' do
|
|
96
|
+
vars = Set[]
|
|
97
|
+
@g.v.as(:a_vertex).in_e(:wrote) { |edge| vars << edge.vars[:a_vertex] }.count
|
|
98
|
+
vars.should == Set[*@g.e.e(:wrote).in_v]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'should not break path generation (simple)' do
|
|
102
|
+
who = nil
|
|
103
|
+
r = @g.v.as(:who).in_e(:wrote).out_v.v { |v|
|
|
104
|
+
who = v.vars[:who]
|
|
105
|
+
}.paths
|
|
106
|
+
r.each do |path|
|
|
107
|
+
path.to_a[0].should == @g
|
|
108
|
+
path.to_a[1].should == who
|
|
109
|
+
path.length.should == 4
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'should not break path generation' do
|
|
114
|
+
who_wrote_what = nil
|
|
115
|
+
r = @g.v.as(:who).in_e(:wrote).as(:wrote).out_v.as(:what).v { |v|
|
|
116
|
+
who_wrote_what = [@g, v.vars[:who], v.vars[:wrote], v.vars[:what]]
|
|
117
|
+
}.paths
|
|
118
|
+
r.each do |path|
|
|
119
|
+
path.to_a.should == who_wrote_what
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
describe :delete! do
|
|
125
|
+
it 'should not try to delete an element twice'
|
|
126
|
+
end
|
|
127
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Enumerable do
|
|
4
|
+
describe '#one?' do
|
|
5
|
+
it 'should be true if there is one element' do
|
|
6
|
+
[:x].one?.should be_true
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should be false if there are no elements' do
|
|
10
|
+
[].one?.should be_false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'should be false if there are 2 elements' do
|
|
14
|
+
[:a, :b].one?.should be_false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should be false if there are lots of elements' do
|
|
18
|
+
([:a, :b] * 100).one?.should be_false
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe '#many?' do
|
|
23
|
+
it 'should be false if there is one element' do
|
|
24
|
+
[:x].many?.should be_false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should be false if there are no elements' do
|
|
28
|
+
[].many?.should be_false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should be true if there are 2 elements' do
|
|
32
|
+
[:a, :b].many?.should be_true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'should be true if there are lots of elements' do
|
|
36
|
+
([:a, :b] * 100).many?.should be_true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe '#to_hashset' do
|
|
41
|
+
it 'should return an empty hashset' do
|
|
42
|
+
[].to_hashset.should == java.util.HashSet.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'should not clone an existing hashset' do
|
|
46
|
+
hs = java.util.HashSet.new
|
|
47
|
+
hs.to_hashset.should equal(hs)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'should create a hashset from an array' do
|
|
51
|
+
hs = java.util.HashSet.new
|
|
52
|
+
hs.add 'a'
|
|
53
|
+
hs.add 'b'
|
|
54
|
+
['a', 'b', 'a'].to_hashset.should == hs
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'should create a hashset from an arraylist' do
|
|
58
|
+
hs = java.util.HashSet.new
|
|
59
|
+
hs.add 'a'
|
|
60
|
+
hs.add 'b'
|
|
61
|
+
al = java.util.ArrayList.new
|
|
62
|
+
al.add 'a'
|
|
63
|
+
al.add 'b'
|
|
64
|
+
al.add 'a'
|
|
65
|
+
al.to_hashset.should == hs
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
Run.tg do
|
|
70
|
+
use_simple_graph_data
|
|
71
|
+
|
|
72
|
+
describe '#to_route' do
|
|
73
|
+
context "from [1, 'a']" do
|
|
74
|
+
context 'with no arguments' do
|
|
75
|
+
subject { [1, 'a'].to_route }
|
|
76
|
+
it { should be_a Pacer::Core::Route }
|
|
77
|
+
its(:element_type) { should == Object }
|
|
78
|
+
its(:to_a) { should == [1, 'a'] }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context 'based on an object route' do
|
|
82
|
+
subject { [1, 'a'].to_route(:based_on => graph.v[:name]) }
|
|
83
|
+
it { should be_a Pacer::Core::Route }
|
|
84
|
+
its(:element_type) { should == Object }
|
|
85
|
+
its(:to_a) { should == [1, 'a'] }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
context 'based on an object route with an extension' do
|
|
89
|
+
subject { [1, 'a'].to_route(:based_on => graph.v[:name].add_extension(Tackle::SimpleMixin)) }
|
|
90
|
+
it { should be_a Pacer::Core::Route }
|
|
91
|
+
its(:extensions) { should == Set[Tackle::SimpleMixin] }
|
|
92
|
+
its(:element_type) { should == Object }
|
|
93
|
+
its(:to_a) { should == [1, 'a'] }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context 'from [elements]' do
|
|
98
|
+
let(:elements) { [v0, v1] }
|
|
99
|
+
|
|
100
|
+
context 'based on an element route' do
|
|
101
|
+
subject { elements.to_route(:based_on => graph.v) }
|
|
102
|
+
its(:element_type) { should == graph.element_type(:vertex) }
|
|
103
|
+
its(:to_a) { should == elements }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context 'based on an extended element route' do
|
|
107
|
+
subject { elements.to_route(:based_on => graph.v(Tackle::SimpleMixin)) }
|
|
108
|
+
its(:extensions) { should == Set[Tackle::SimpleMixin] }
|
|
109
|
+
its(:element_type) { should == graph.element_type(:vertex) }
|
|
110
|
+
its(:to_a) { should == elements }
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
Run.tg :read_only do
|
|
4
|
+
use_pacer_graphml_data :read_only
|
|
5
|
+
|
|
6
|
+
describe Pacer::Transform::Join do
|
|
7
|
+
context 'with no key or value specified' do
|
|
8
|
+
subject { graph.v.join }
|
|
9
|
+
its(:count) { should == 7 }
|
|
10
|
+
specify 'each element should be a node' do
|
|
11
|
+
subject.each do |group|
|
|
12
|
+
group[:key].should be_a graph.element_type(:vertex)
|
|
13
|
+
group.property_keys.to_a.should == ['key']
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'with key_route only' do
|
|
19
|
+
subject { graph.v.join(:key) { |r| r[:type] } }
|
|
20
|
+
|
|
21
|
+
its(:count) { should == 7 }
|
|
22
|
+
its(:to_a) { should_not be_empty }
|
|
23
|
+
specify 'each result should have one value' do
|
|
24
|
+
subject.each do |group|
|
|
25
|
+
group[:key].should be_a String
|
|
26
|
+
group.property_keys.to_a.should == ['key']
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'with key_route and value route' do
|
|
32
|
+
let(:route) { graph.v.join(:key) { |r| r[:type] }.join }
|
|
33
|
+
subject { route }
|
|
34
|
+
|
|
35
|
+
specify 'each result should reflect an element' do
|
|
36
|
+
subject.each.zip(graph.v.to_a) do |group, e|
|
|
37
|
+
group[:key].should == e[:type]
|
|
38
|
+
group.property_keys.to_set.should == Set['key', 'values']
|
|
39
|
+
group[:values].last.element_id.should == e.element_id
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context '#multigraph' do
|
|
44
|
+
subject { route.multigraph }
|
|
45
|
+
it { should be_a Pacer::MultiGraph }
|
|
46
|
+
|
|
47
|
+
its('v.count') { should == 3 }
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
context 'person' do
|
|
51
|
+
subject { route.multigraph.vertex 'person' }
|
|
52
|
+
it 'should hove 2 values' do
|
|
53
|
+
subject[:values].length.should == 2
|
|
54
|
+
end
|
|
55
|
+
it { subject[:values].should == graph.v(:type => 'person').to_a }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context 'project' do
|
|
59
|
+
subject { route.multigraph.vertex 'project' }
|
|
60
|
+
it 'should hove 2 values' do
|
|
61
|
+
subject[:values].length.should == 4
|
|
62
|
+
end
|
|
63
|
+
it { subject[:values].should == graph.v(:type => 'project').to_a }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'reduced to a count' do
|
|
67
|
+
subject do
|
|
68
|
+
route.multigraph.v.reduce({}) do |h, v|
|
|
69
|
+
h[v.element_id] = v[:values].count
|
|
70
|
+
h
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
specify 'it should have a count for values' do
|
|
74
|
+
subject['project'].should == 4
|
|
75
|
+
subject['person'].should == 2
|
|
76
|
+
subject['group'].should == 1
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context 'reduced to a string' do
|
|
81
|
+
subject do
|
|
82
|
+
route.multigraph.v.reduce({}) do |h, v|
|
|
83
|
+
h[v.element_id] = v[:values].map { |v| v[:name] }.join ', '
|
|
84
|
+
h
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
specify do
|
|
88
|
+
subject['project'].should == 'blueprints, pipes, pacer, gremlin'
|
|
89
|
+
subject['person'].should == 'pangloss, okram'
|
|
90
|
+
subject['group'].should == 'tinkerpop'
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context 'with a key block that returns a literal value' do
|
|
97
|
+
subject { graph.v.join { |r| r[:type] }.key { |r| r[:type].length } }
|
|
98
|
+
its(:count) { should == 7 }
|
|
99
|
+
specify 'each value should have a numeric key' do
|
|
100
|
+
subject.each do |v|
|
|
101
|
+
v[:key].should == v.element_id
|
|
102
|
+
v[:key].should == v[:values].first.length
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context 'with values_maps' do
|
|
108
|
+
let(:counted_group) do
|
|
109
|
+
graph.v.join(:count) { |r| r.out_e.counted.cap }.
|
|
110
|
+
join(:out_e, &:out_e).
|
|
111
|
+
key { |r| r[:type] }
|
|
112
|
+
end
|
|
113
|
+
subject do
|
|
114
|
+
counted_group.multigraph
|
|
115
|
+
end
|
|
116
|
+
its('v.count') { should == 3 }
|
|
117
|
+
specify { counted_group.count.should == 7 }
|
|
118
|
+
specify 'combine(:count) should group the counts in a hash' do
|
|
119
|
+
hash = Hash[subject.v[[:key, :count]].to_a]
|
|
120
|
+
hash.should == {"project"=>[0, 1, 3, 2], "person"=>[1, 3], "group"=>[4]}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
specify 'reduce summarizes edge labels for each type' do
|
|
124
|
+
result = Hash[subject.v.map { |v| [v.element_id, v[:out_e].group_count { |e| e.label }] }.to_a]
|
|
125
|
+
result.should == {"project" => {"uses" => 5, "modelled_on" => 1},
|
|
126
|
+
"person" => {"wrote" => 4},
|
|
127
|
+
"group" => {"projects" => 3, "member" => 1}}
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
its(:inspect) { should == "#<MultiGraph>" }
|
|
131
|
+
|
|
132
|
+
specify do
|
|
133
|
+
counted_group.inspect.should ==
|
|
134
|
+
"#<GraphV -> V-Join(#<V -> Obj(type)>: {:count=>#<V -> outE -> Obj-Cap(E-Counted)>, :out_e=>#<V -> outE>})>"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Pacer::Transform::Path do
|
|
4
|
+
before :all do
|
|
5
|
+
@g = Pacer.tg 'spec/data/pacer.graphml'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe '#paths' do
|
|
9
|
+
it 'should return the paths between people and projects' do
|
|
10
|
+
Set[*@g.v(:type => 'person').out_e.in_v(:type => 'project').paths.collect(&:to_a)].should ==
|
|
11
|
+
Set[[@g.vertex(0), @g.edge(0), @g.vertex(1)],
|
|
12
|
+
[@g.vertex(5), @g.edge(1), @g.vertex(4)],
|
|
13
|
+
[@g.vertex(5), @g.edge(13), @g.vertex(2)],
|
|
14
|
+
[@g.vertex(5), @g.edge(12), @g.vertex(3)]]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should include all elements traversed' do
|
|
18
|
+
@g.v.out_e.in_v.paths.each do |path|
|
|
19
|
+
path[0].should == @g
|
|
20
|
+
path[1].should be_a(Pacer::TinkerVertex)
|
|
21
|
+
path[2].should be_a(Pacer::TinkerEdge)
|
|
22
|
+
path[3].should be_a(Pacer::TinkerVertex)
|
|
23
|
+
path.length.should == 4
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe '#transpose' do
|
|
30
|
+
it 'should return the paths between people and projects' do
|
|
31
|
+
transposed = @g.v(:type => 'person').out_e.in_v(:type => 'project').paths.transpose
|
|
32
|
+
Set[*transposed].should ==
|
|
33
|
+
Set[[@g.vertex(0), @g.vertex(5), @g.vertex(5), @g.vertex(5)],
|
|
34
|
+
[@g.edge(0), @g.edge(1), @g.edge(13), @g.edge(12)],
|
|
35
|
+
[@g.vertex(1), @g.vertex(4), @g.vertex(2), @g.vertex(3)]]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe '#subgraph' do
|
|
40
|
+
before do
|
|
41
|
+
@sg = @g.v(:type => 'person').out_e.in_v(:type => 'project').subgraph
|
|
42
|
+
|
|
43
|
+
@vertices = @g.v(:type => 'person').to_a + @g.v(:type => 'project').to_a
|
|
44
|
+
@edges = @g.v(:type => 'person').out_e(:wrote)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it { Set[*@sg.v.element_ids].should == Set[*@vertices.collect { |v| v.element_id }] }
|
|
48
|
+
it { Set[*@sg.e.element_ids].should == Set[*@edges.collect { |e| e.element_id }] }
|
|
49
|
+
|
|
50
|
+
it { @sg.e.labels.uniq.to_a.should == ['wrote'] }
|
|
51
|
+
it { Set[*@sg.v.collect { |v| v.properties }].should == Set[*@vertices.collect { |v| v.properties }] }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Pacer::Utils::TSort do
|
|
4
|
+
let(:graph) { Pacer.tg }
|
|
5
|
+
|
|
6
|
+
context 'single vertex' do
|
|
7
|
+
before do
|
|
8
|
+
graph.create_vertex
|
|
9
|
+
end
|
|
10
|
+
let(:node) { graph.v(Pacer::Utils::TSort).first }
|
|
11
|
+
|
|
12
|
+
describe 'tsort()' do
|
|
13
|
+
subject { node.tsort.to_a }
|
|
14
|
+
it { should == [node] }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'breakfast example' do
|
|
19
|
+
let(:breakfast) { graph.create_vertex 'breakfast' }
|
|
20
|
+
let(:serve) { graph.create_vertex 'serve' }
|
|
21
|
+
let(:cook) { graph.create_vertex 'cook' }
|
|
22
|
+
let(:eggs) { graph.create_vertex 'buy eggs' }
|
|
23
|
+
let(:bacon) { graph.create_vertex 'buy bacon' }
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
[eggs, bacon].to_route(:graph => graph, :element_type => :vertex).add_edges_to :requires, cook
|
|
27
|
+
cook.add_edges_to :requires, serve
|
|
28
|
+
serve.add_edges_to :requires, breakfast
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'whole meal' do
|
|
32
|
+
subject do
|
|
33
|
+
graph.v(Pacer::Utils::TSort).tsort.to_a
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it { should == [ bacon, eggs, cook, serve, breakfast ] }
|
|
37
|
+
|
|
38
|
+
it 'should be different from the default order' do
|
|
39
|
+
should_not == graph.v.to_a
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'from one vertex' do
|
|
44
|
+
subject do
|
|
45
|
+
graph.v(Pacer::Utils::TSort).only(cook).tsort.to_a
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it { should == [ bacon, eggs, cook ] }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context 'circular' do
|
|
53
|
+
let(:a) { graph.create_vertex 'a' }
|
|
54
|
+
let(:b) { graph.create_vertex 'b' }
|
|
55
|
+
let(:c) { graph.create_vertex 'c' }
|
|
56
|
+
|
|
57
|
+
before do
|
|
58
|
+
a.add_edges_to :needs, b
|
|
59
|
+
b.add_edges_to :needs, c
|
|
60
|
+
c.add_edges_to :needs, a
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'should raise a TSort::Cyclic error' do
|
|
64
|
+
proc {
|
|
65
|
+
graph.v(Pacer::Utils::TSort).tsort
|
|
66
|
+
}.should raise_error TSort::Cyclic
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'can not TSort a subset of a cyclical graph' do
|
|
70
|
+
proc {
|
|
71
|
+
graph.v(Pacer::Utils::TSort).only([a,b]).tsort.should == [a,b]
|
|
72
|
+
}.should raise_error TSort::Cyclic
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'can be worked around with subgraph' do
|
|
76
|
+
vertices = graph.v.only([a,b]).result
|
|
77
|
+
edges = graph.e.lookahead(:min => 2) { |e| e.both_v.only(vertices) }.result
|
|
78
|
+
subgraph = (vertices.to_a + edges.to_a).to_route(:graph => graph, :element_type => :mixed).subgraph
|
|
79
|
+
# The elements aren't the same since they've been copied into a
|
|
80
|
+
# new graph:
|
|
81
|
+
subgraph.v(Pacer::Utils::TSort).tsort.element_ids.to_a.should == ['b', 'a']
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'can be sorted with a custom dependencies block' do
|
|
85
|
+
graph.v(Pacer::Utils::TSort).dependencies { |v| v.in.except(c) }.tsort.to_a.should ==
|
|
86
|
+
[a, b, c]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
Run.all :read_only do
|
|
4
|
+
use_pacer_graphml_data :read_only
|
|
5
|
+
|
|
6
|
+
describe Pacer::Wrappers::EdgeWrapper do
|
|
7
|
+
|
|
8
|
+
let(:e_exts) { [Tackle::SimpleMixin, TP::Wrote] }
|
|
9
|
+
let(:e_wrapper_class) { Pacer::Wrappers::EdgeWrapper.wrapper_for e_exts }
|
|
10
|
+
|
|
11
|
+
subject { e_wrapper_class }
|
|
12
|
+
|
|
13
|
+
it { should_not be_nil }
|
|
14
|
+
its(:route_conditions) { should == { label: 'wrote' } }
|
|
15
|
+
its(:extensions) { should == e_exts }
|
|
16
|
+
|
|
17
|
+
describe 'instance' do
|
|
18
|
+
subject { e_wrapper_class.new pangloss_wrote_pacer }
|
|
19
|
+
it { should_not be_nil }
|
|
20
|
+
its(:element) { should_not be_nil }
|
|
21
|
+
it { should == pangloss_wrote_pacer }
|
|
22
|
+
it { should_not equal pangloss_wrote_pacer }
|
|
23
|
+
its(:element_id) { should == pangloss_wrote_pacer.element_id }
|
|
24
|
+
its(:extensions) { should == e_exts }
|
|
25
|
+
|
|
26
|
+
describe 'with more extensions added' do
|
|
27
|
+
subject { e_wrapper_class.new(pacer).add_extensions([Pacer::Utils::TSort]) }
|
|
28
|
+
its(:class) { should_not == e_wrapper_class }
|
|
29
|
+
its(:extensions) { should == e_exts + [Pacer::Utils::TSort] }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|