ul-wukong 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +60 -0
- data/.gitmodules +6 -0
- data/.rspec +2 -0
- data/.travis.yml +19 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +17 -0
- data/Guardfile +12 -0
- data/LICENSE.md +95 -0
- data/NOTES-travis.md +31 -0
- data/README-old.md +422 -0
- data/README.md +1308 -0
- data/Rakefile +28 -0
- data/TODO.md +99 -0
- data/bin/cutc +30 -0
- data/bin/cuttab +5 -0
- data/bin/greptrue +6 -0
- data/bin/md5sort +20 -0
- data/bin/setcat +11 -0
- data/bin/tabchar +5 -0
- data/bin/uniq-ord +59 -0
- data/bin/uniqc +3 -0
- data/bin/wu +34 -0
- data/bin/wu-clean-encoding +31 -0
- data/bin/wu-date +13 -0
- data/bin/wu-datetime +13 -0
- data/bin/wu-hist +3 -0
- data/bin/wu-lign +186 -0
- data/bin/wu-local +4 -0
- data/bin/wu-plus +9 -0
- data/bin/wu-source +5 -0
- data/bin/wu-sum +31 -0
- data/diagrams/wu_local.dot +39 -0
- data/diagrams/wu_local.dot.png +0 -0
- data/examples/Gemfile +38 -0
- data/examples/README.md +9 -0
- data/examples/basic/string_reverser.rb +23 -0
- data/examples/basic/tiny_count.rb +8 -0
- data/examples/basic/word_count/accumulator.rb +26 -0
- data/examples/basic/word_count/tokenizer.rb +13 -0
- data/examples/basic/word_count/word_count.rb +6 -0
- data/examples/dataflow/scraper_macro_flow.rb +28 -0
- data/examples/deploy_pack/Gemfile +6 -0
- data/examples/deploy_pack/README.md +6 -0
- data/examples/deploy_pack/a/b/c/.gitkeep +0 -0
- data/examples/deploy_pack/app/processors/string_reverser.rb +5 -0
- data/examples/deploy_pack/config/environment.rb +1 -0
- data/examples/dsl/dataflow/fibonacci_series.rb +101 -0
- data/examples/dsl/dataflow/scraper_macro_flow.rb +28 -0
- data/examples/dsl/dataflow/simple.rb +12 -0
- data/examples/dsl/dataflow/telegram.rb +45 -0
- data/examples/dsl/workflow/cherry_pie.dot +97 -0
- data/examples/dsl/workflow/cherry_pie.md +104 -0
- data/examples/dsl/workflow/cherry_pie.png +0 -0
- data/examples/dsl/workflow/cherry_pie.rb +101 -0
- data/examples/empty/.gitkeep +0 -0
- data/examples/examples_helper.rb +9 -0
- data/examples/geo.rb +4 -0
- data/examples/geo/geo_grids.numbers +0 -0
- data/examples/geo/geolocated.rb +331 -0
- data/examples/geo/quadtile.rb +69 -0
- data/examples/geo/spec/geolocated_spec.rb +247 -0
- data/examples/geo/tile_fetcher.rb +77 -0
- data/examples/graph/implied_geolocation/README.md +63 -0
- data/examples/graph/minimum_spanning_tree/airfares_graphviz.rb +73 -0
- data/examples/improver/tweet_summary.rb +73 -0
- data/examples/loadable.rb +2 -0
- data/examples/munging/airline_flights/airline_flights.rake +83 -0
- data/examples/munging/airline_flights/airplane.rb +0 -0
- data/examples/munging/airline_flights/airport_id_unification.rb +129 -0
- data/examples/munging/airline_flights/airport_ok_chars.rb +4 -0
- data/examples/munging/airline_flights/indexable.rb +75 -0
- data/examples/munging/airline_flights/indexable_spec.rb +90 -0
- data/examples/munging/airline_flights/reconcile_airports.rb +142 -0
- data/examples/munging/airline_flights/tasks.rake +83 -0
- data/examples/munging/airline_flights/topcities.rb +167 -0
- data/examples/munging/geo/geo_json.rb +54 -0
- data/examples/munging/geo/geo_models.rb +69 -0
- data/examples/munging/geo/geonames_models.rb +107 -0
- data/examples/munging/geo/iso_codes.rb +172 -0
- data/examples/munging/geo/reconcile_countries.rb +124 -0
- data/examples/munging/geo/tasks.rake +71 -0
- data/examples/munging/wikipedia/articles/extract_articles-parsed.rb +79 -0
- data/examples/munging/wikipedia/articles/extract_articles-templated.rb +136 -0
- data/examples/munging/wikipedia/articles/textualize_articles.rb +54 -0
- data/examples/munging/wikipedia/articles/verify_structure.rb +43 -0
- data/examples/munging/wikipedia/articles/wp2txt-LICENSE.txt +22 -0
- data/examples/munging/wikipedia/articles/wp2txt_article.rb +259 -0
- data/examples/munging/wikipedia/articles/wp2txt_utils.rb +452 -0
- data/examples/munging/wikipedia/dbpedia/dbpedia_common.rb +5 -0
- data/examples/munging/wikipedia/dbpedia/dbpedia_extract_geocoordinates.rb +78 -0
- data/examples/munging/wikipedia/dbpedia/extract_links-cruft.rb +66 -0
- data/examples/munging/wikipedia/dbpedia/extract_links.rb +260 -0
- data/examples/munging/wikipedia/dbpedia/sameas_extractor.rb +20 -0
- data/examples/rake_helper.rb +97 -0
- data/examples/ruby_project/Gemfile +6 -0
- data/examples/ruby_project/README.md +6 -0
- data/examples/ruby_project/a/b/c/.gitkeep +0 -0
- data/examples/server_logs/geo_ip_mapping/munge_geolite.rb +82 -0
- data/examples/server_logs/logline.rb +95 -0
- data/examples/server_logs/models.rb +66 -0
- data/examples/server_logs/page_counts.pig +48 -0
- data/examples/server_logs/server_logs-01-parse-script.rb +13 -0
- data/examples/server_logs/server_logs-02-histograms-full.rb +33 -0
- data/examples/server_logs/server_logs-02-histograms-mapper.rb +14 -0
- data/examples/server_logs/server_logs-03-breadcrumbs-full.rb +71 -0
- data/examples/server_logs/server_logs-04-page_page_edges-full.rb +40 -0
- data/examples/serverlogs/geo_ip_mapping/munge_geolite.rb +82 -0
- data/examples/serverlogs/models/logline.rb +102 -0
- data/examples/serverlogs/parser/apache_parser_widget.rb +46 -0
- data/examples/serverlogs/visit_paths/common.rb +4 -0
- data/examples/serverlogs/visit_paths/page_counts.pig +48 -0
- data/examples/serverlogs/visit_paths/serverlogs-01-parse-script.rb +11 -0
- data/examples/serverlogs/visit_paths/serverlogs-02-histograms-full.rb +31 -0
- data/examples/serverlogs/visit_paths/serverlogs-02-histograms-mapper.rb +12 -0
- data/examples/serverlogs/visit_paths/serverlogs-03-breadcrumbs-full.rb +67 -0
- data/examples/serverlogs/visit_paths/serverlogs-04-page_page_edges-full.rb +38 -0
- data/examples/splitter.rb +94 -0
- data/examples/string_reverser.rb +7 -0
- data/examples/text/pig_latin/pig_latinizer.rb +35 -0
- data/examples/text/pig_latin/pig_latinizer_widget.rb +16 -0
- data/examples/text/regional_flavor/README.md +14 -0
- data/examples/text/regional_flavor/article_wordbags.pig +39 -0
- data/examples/text/regional_flavor/j01-article_wordbags.rb +4 -0
- data/examples/text/regional_flavor/simple_pig_script.pig +27 -0
- data/examples/twitter.rb +5 -0
- data/lib/hanuman.rb +36 -0
- data/lib/hanuman/graph.rb +97 -0
- data/lib/hanuman/graphvizzer.rb +206 -0
- data/lib/hanuman/graphvizzer/gv_models.rb +161 -0
- data/lib/hanuman/graphvizzer/gv_presenter.rb +97 -0
- data/lib/hanuman/link.rb +35 -0
- data/lib/hanuman/registry.rb +46 -0
- data/lib/hanuman/stage.rb +128 -0
- data/lib/hanuman/tree.rb +67 -0
- data/lib/wu/geo.rb +4 -0
- data/lib/wu/geo/geo_grids.numbers +0 -0
- data/lib/wu/geo/geolocated.rb +331 -0
- data/lib/wu/geo/quadtile.rb +69 -0
- data/lib/wu/graph/union_find.rb +62 -0
- data/lib/wu/model/reconcilable.rb +63 -0
- data/lib/wu/munging.rb +71 -0
- data/lib/wu/social/models/twitter.rb +31 -0
- data/lib/wu/wikipedia/models.rb +20 -0
- data/lib/wukong.rb +54 -0
- data/lib/wukong/dataflow.rb +43 -0
- data/lib/wukong/doc_helpers.rb +14 -0
- data/lib/wukong/doc_helpers/dataflow_handler.rb +29 -0
- data/lib/wukong/doc_helpers/field_handler.rb +91 -0
- data/lib/wukong/doc_helpers/processor_handler.rb +29 -0
- data/lib/wukong/driver.rb +214 -0
- data/lib/wukong/driver/event_machine_driver.rb +15 -0
- data/lib/wukong/driver/wiring.rb +68 -0
- data/lib/wukong/local.rb +42 -0
- data/lib/wukong/local/runner.rb +96 -0
- data/lib/wukong/local/stdio_driver.rb +104 -0
- data/lib/wukong/logger.rb +102 -0
- data/lib/wukong/model/faker.rb +136 -0
- data/lib/wukong/model/flatpack_parser/flat.rb +60 -0
- data/lib/wukong/model/flatpack_parser/flatpack.rb +4 -0
- data/lib/wukong/model/flatpack_parser/lang.rb +46 -0
- data/lib/wukong/model/flatpack_parser/parser.rb +55 -0
- data/lib/wukong/model/flatpack_parser/tokens.rb +130 -0
- data/lib/wukong/plugin.rb +48 -0
- data/lib/wukong/processor.rb +110 -0
- data/lib/wukong/rake_helper.rb +6 -0
- data/lib/wukong/runner.rb +169 -0
- data/lib/wukong/runner/boot_sequence.rb +123 -0
- data/lib/wukong/runner/code_loader.rb +52 -0
- data/lib/wukong/runner/command_runner.rb +44 -0
- data/lib/wukong/runner/deploy_pack_loader.rb +75 -0
- data/lib/wukong/runner/help_message.rb +42 -0
- data/lib/wukong/source.rb +33 -0
- data/lib/wukong/source/source_driver.rb +74 -0
- data/lib/wukong/source/source_runner.rb +38 -0
- data/lib/wukong/spec_helpers.rb +74 -0
- data/lib/wukong/spec_helpers/integration_tests.rb +150 -0
- data/lib/wukong/spec_helpers/integration_tests/integration_test_matchers.rb +207 -0
- data/lib/wukong/spec_helpers/integration_tests/integration_test_runner.rb +97 -0
- data/lib/wukong/spec_helpers/shared_examples.rb +22 -0
- data/lib/wukong/spec_helpers/unit_tests.rb +135 -0
- data/lib/wukong/spec_helpers/unit_tests/unit_test_driver.rb +132 -0
- data/lib/wukong/spec_helpers/unit_tests/unit_test_matchers.rb +169 -0
- data/lib/wukong/spec_helpers/unit_tests/unit_test_runner.rb +60 -0
- data/lib/wukong/version.rb +3 -0
- data/lib/wukong/widget/echo.rb +55 -0
- data/lib/wukong/widget/extract.rb +122 -0
- data/lib/wukong/widget/filters.rb +452 -0
- data/lib/wukong/widget/logger.rb +56 -0
- data/lib/wukong/widget/operators.rb +82 -0
- data/lib/wukong/widget/reducers.rb +10 -0
- data/lib/wukong/widget/reducers/accumulator.rb +73 -0
- data/lib/wukong/widget/reducers/bin.rb +368 -0
- data/lib/wukong/widget/reducers/count.rb +73 -0
- data/lib/wukong/widget/reducers/group.rb +128 -0
- data/lib/wukong/widget/reducers/group_concat.rb +98 -0
- data/lib/wukong/widget/reducers/improver.rb +71 -0
- data/lib/wukong/widget/reducers/join_xml.rb +37 -0
- data/lib/wukong/widget/reducers/moments.rb +72 -0
- data/lib/wukong/widget/reducers/sort.rb +180 -0
- data/lib/wukong/widget/reducers/uniq.rb +91 -0
- data/lib/wukong/widget/serializers.rb +317 -0
- data/lib/wukong/widget/utils.rb +46 -0
- data/lib/wukong/widgets.rb +7 -0
- data/spec/examples/dataflow/fibonacci_series_spec.rb +18 -0
- data/spec/examples/dataflow/parse_apache_logs_spec.rb +8 -0
- data/spec/examples/dataflow/parsing_spec.rb +14 -0
- data/spec/examples/dataflow/simple_spec.rb +34 -0
- data/spec/examples/dataflow/telegram_spec.rb +43 -0
- data/spec/examples/graph/minimum_spanning_tree_spec.rb +34 -0
- data/spec/examples/munging/airline_flights/identifiers_spec.rb +16 -0
- data/spec/examples/munging/airline_flights_spec.rb +202 -0
- data/spec/examples/text/pig_latin_spec.rb +18 -0
- data/spec/examples/workflow/cherry_pie_spec.rb +36 -0
- data/spec/hanuman/graph_spec.rb +119 -0
- data/spec/hanuman/hanuman_spec.rb +10 -0
- data/spec/hanuman/registry_spec.rb +123 -0
- data/spec/hanuman/stage_spec.rb +81 -0
- data/spec/hanuman/tree_spec.rb +119 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/example_test_helpers.rb +95 -0
- data/spec/support/hanuman_test_helpers.rb +92 -0
- data/spec/support/integration_helper.rb +38 -0
- data/spec/support/model_test_helpers.rb +115 -0
- data/spec/support/shared_context_for_graphs.rb +57 -0
- data/spec/support/shared_context_for_reducers.rb +37 -0
- data/spec/support/shared_examples_for_builders.rb +94 -0
- data/spec/support/shared_examples_for_shortcuts.rb +57 -0
- data/spec/wu/model/reconcilable_spec.rb +152 -0
- data/spec/wukong/dataflow_spec.rb +87 -0
- data/spec/wukong/driver_spec.rb +154 -0
- data/spec/wukong/local/runner_spec.rb +29 -0
- data/spec/wukong/local/stdio_driver_spec.rb +73 -0
- data/spec/wukong/local_spec.rb +6 -0
- data/spec/wukong/logger_spec.rb +49 -0
- data/spec/wukong/model/faker_spec.rb +132 -0
- data/spec/wukong/processor_spec.rb +21 -0
- data/spec/wukong/runner_spec.rb +132 -0
- data/spec/wukong/source_spec.rb +6 -0
- data/spec/wukong/widget/extract_spec.rb +101 -0
- data/spec/wukong/widget/filters_spec.rb +79 -0
- data/spec/wukong/widget/logger_spec.rb +23 -0
- data/spec/wukong/widget/operators_spec.rb +25 -0
- data/spec/wukong/widget/reducers/bin_spec.rb +92 -0
- data/spec/wukong/widget/reducers/count_spec.rb +11 -0
- data/spec/wukong/widget/reducers/group_spec.rb +21 -0
- data/spec/wukong/widget/reducers/join_xml_spec.rb +25 -0
- data/spec/wukong/widget/reducers/moments_spec.rb +36 -0
- data/spec/wukong/widget/reducers/sort_spec.rb +26 -0
- data/spec/wukong/widget/reducers/uniq_spec.rb +14 -0
- data/spec/wukong/widget/serializers_spec.rb +114 -0
- data/spec/wukong/widget/sink_spec.rb +19 -0
- data/spec/wukong/widget/source_spec.rb +65 -0
- data/spec/wukong/wu-local_spec.rb +109 -0
- data/spec/wukong/wu-source_spec.rb +32 -0
- data/spec/wukong/wu_spec.rb +14 -0
- data/spec/wukong/wukong_spec.rb +10 -0
- data/wukong.gemspec +35 -0
- metadata +465 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
# require 'wukong'
|
3
|
+
|
4
|
+
# require 'hanuman/graphvizzer/gv_presenter'
|
5
|
+
|
6
|
+
# describe 'cherry_pie' do
|
7
|
+
|
8
|
+
# # it 'fiddles' do
|
9
|
+
# # load(Pathname.path_to(:examples, 'workflow/cherry_pie.rb'))
|
10
|
+
# # Wukong.workflow(:cherry_pie) do
|
11
|
+
# # Log.dump self
|
12
|
+
# #
|
13
|
+
# # graph(:crust) do
|
14
|
+
# # Log.dump self
|
15
|
+
# # action(:bob)
|
16
|
+
# # end
|
17
|
+
# #
|
18
|
+
# # Log.dump graph(:crust)
|
19
|
+
# #
|
20
|
+
# # end
|
21
|
+
# # end
|
22
|
+
|
23
|
+
|
24
|
+
# describe 'Graphviz View', :if => GRAPHVIZ do
|
25
|
+
# it 'makes a png' do
|
26
|
+
# require Pathname.path_to(:examples, 'workflow/cherry_pie.rb')
|
27
|
+
|
28
|
+
# gv = Wukong.to_graphviz
|
29
|
+
|
30
|
+
# basename = Pathname.path_to(:tmp, 'cherry_pie')
|
31
|
+
# gv.save(basename, 'png')
|
32
|
+
# puts File.read("#{basename}.dot")
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
|
36
|
+
# end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hanuman::Graph, :hanuman => true do
|
4
|
+
|
5
|
+
include_context "graphs"
|
6
|
+
|
7
|
+
context "#ancestors" do
|
8
|
+
context "called without any arguments" do
|
9
|
+
it "returns all stages with an ancestor" do
|
10
|
+
graph.ancestors.size.should == 4
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "called with a stage as the first argument" do
|
15
|
+
it "returns the immediate ancestors of the stage" do
|
16
|
+
graph.ancestors(graph.stages[:second]).size.should == 2
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "#descendents" do
|
22
|
+
context "called without any arguments" do
|
23
|
+
it "returns all stages with a descendent" do
|
24
|
+
graph.descendents.size.should == 4
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "called with a stage as the first argument" do
|
29
|
+
it "returns the immediate descendents of the stage" do
|
30
|
+
graph.descendents(graph.stages[:second]).size.should == 2
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "#add_stage" do
|
36
|
+
let(:stage) { Hanuman::Stage.receive(label: :orphan) }
|
37
|
+
it "adds the stage to the graph" do
|
38
|
+
expect { graph.add_stage(stage) }.to change { graph.stages[:orphan] }.from(nil).to(stage)
|
39
|
+
end
|
40
|
+
it "doesn't create any links" do
|
41
|
+
expect { graph.add_stage(stage) }.to_not change { graph.links }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "#add_link" do
|
46
|
+
context "when adding a new stage" do
|
47
|
+
let(:from) { graph.stages[:fourth] }
|
48
|
+
let(:into) { Hanuman::Stage.receive(label: :fifth) }
|
49
|
+
it "adds the new stage to the graph" do
|
50
|
+
expect { graph.add_link(:simple, from, into) }.to change { graph.stages[:fifth] }.from(nil).to(into)
|
51
|
+
end
|
52
|
+
it "adds the new link to the graph" do
|
53
|
+
expect { graph.add_link(:simple, from, into) }.to change { graph.links.size }.by(1)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
context "when adding an existing link" do
|
57
|
+
let(:from) { graph.stages[:third_a] }
|
58
|
+
let(:into) { graph.stages[:fourth] }
|
59
|
+
it "duplicates the link in the graph" do
|
60
|
+
expect { graph.add_link(:simple, from, into) }.to change { graph.links.size }.by(1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
context "when making a cycle" do
|
64
|
+
let(:from) { graph.stages[:fourth] }
|
65
|
+
let(:into) { graph.stages[:first_a] }
|
66
|
+
it "adds the link in the graph" do
|
67
|
+
expect { graph.add_link(:simple, from, into) }.to change { graph.links.size }.by(1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
context "when linking a stage to itself" do
|
71
|
+
let(:from) { tree.stages[:fourth] }
|
72
|
+
let(:into) { tree.stages[:fourth] }
|
73
|
+
it "adds the link in the graph" do
|
74
|
+
expect { graph.add_link(:simple, from, into) }.to change { graph.links.size }.by(1)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe Hanuman::GraphBuilder, :hanuman => true do
|
82
|
+
|
83
|
+
it_behaves_like 'a Stage::Builder'
|
84
|
+
|
85
|
+
its(:namespace){ should be(Hanuman::Graph) }
|
86
|
+
|
87
|
+
context '#define' do
|
88
|
+
let(:block_arg){ ->(){ def say() "I'm the Juggernaut!" ; end } }
|
89
|
+
|
90
|
+
it 'evalutes a supplied block itself' do
|
91
|
+
subject.label = :juggernaut
|
92
|
+
subject.should_receive(:instance_eval).with(&block_arg)
|
93
|
+
subject.define(&block_arg)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context '#build' do
|
98
|
+
before do
|
99
|
+
Wukong.processor(:foo) do
|
100
|
+
field :bones, String
|
101
|
+
end
|
102
|
+
Wukong.dataflow(:bar) do
|
103
|
+
foo
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
let(:graph){ Wukong.registry.retrieve(:bar) }
|
108
|
+
it 'builds stages with specific options' do
|
109
|
+
built = graph.build(foo: { bones: 'lala' })
|
110
|
+
built.stages[:foo].bones.should eq('lala')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context '#serialize' do
|
115
|
+
it 'serializes into a Hash with stages and links' do
|
116
|
+
subject.serialize.should include(:stages, :links)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hanuman::Registry, :hanuman => true do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@orig_reg = Hanuman.registry.show
|
7
|
+
Hanuman.registry.clear!
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:each) do
|
11
|
+
Hanuman.registry.clear!
|
12
|
+
Hanuman.registry.merge!(@orig_reg)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:definition){ { :universe => 'Marvel' } }
|
16
|
+
let(:builder) { Hanuman::StageBuilder.receive(definition) }
|
17
|
+
|
18
|
+
context '#create' do
|
19
|
+
context 'non-existing entry' do
|
20
|
+
it 'creates a new entry for supplied definition' do
|
21
|
+
subject.create(:storm, builder).should be true
|
22
|
+
subject.should be_registered(:storm)
|
23
|
+
subject.retrieve(:storm).should == builder
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'existing' do
|
28
|
+
it 'does not create a new entry' do
|
29
|
+
subject.create(:storm, builder)
|
30
|
+
subject.create(:storm, builder).should be false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context '#update' do
|
36
|
+
context 'non-existing entry' do
|
37
|
+
it 'does not update the entry' do
|
38
|
+
subject.update(:rogue, definition).should be false
|
39
|
+
subject.should_not be_registered(:rogue)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'existing' do
|
44
|
+
let(:new_definition){ { :universe => 'alternate' } }
|
45
|
+
|
46
|
+
it 'updates the entry' do
|
47
|
+
subject.create(:rogue, builder)
|
48
|
+
subject.update(:rogue, new_definition).should be true
|
49
|
+
subject.retrieve(:rogue).serialize.should include(new_definition)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context '#create_or_update' do
|
55
|
+
context 'non-existing entry' do
|
56
|
+
it 'creates the entry' do
|
57
|
+
subject.should_not be_registered(:cyclops)
|
58
|
+
subject.create_or_update(:cyclops, definition).should be true
|
59
|
+
subject.retrieve(:cyclops).should == definition
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'existing' do
|
64
|
+
let(:new_definition){ { :universe => 'alternate' } }
|
65
|
+
|
66
|
+
it 'updates the entry' do
|
67
|
+
subject.create(:cyclops, builder)
|
68
|
+
subject.create_or_update(:cyclops, new_definition).should be true
|
69
|
+
subject.retrieve(:cyclops).serialize.should include(new_definition)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context '#decorate_with_registry' do
|
75
|
+
let(:graph_builder){ Hanuman::GraphBuilder.receive(label: :beastman) }
|
76
|
+
let(:definition) { Hanuman::StageBuilder.receive(label: :mystique) }
|
77
|
+
|
78
|
+
before(:each) do
|
79
|
+
subject.create(:mystique, definition)
|
80
|
+
subject.decorate_with_registry(graph_builder)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'decorates a builder with the registry entries as methods' do
|
84
|
+
graph_builder.should respond_to(:mystique)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'decorates using singleton method definitions' do
|
88
|
+
graph_builder.dup.should_not respond_to(:mystique)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'returns an instance of Hanuman::StageBuilder for chaining' do
|
92
|
+
graph_builder.send(:mystique).should be_instance_of(Hanuman::StageBuilder)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'adds the instance of Hanuman::StageBuilder to its :stages attribute when used' do
|
96
|
+
graph_builder.stages.should_not include(:mystique)
|
97
|
+
graph_builder.send(:mystique)
|
98
|
+
graph_builder.stages.should include(:mystique)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'retrieves the Hanuman::StageBuilder from the registry' do
|
102
|
+
Hanuman.registry.should_receive(:retrieve).with(:mystique).and_return(definition)
|
103
|
+
graph_builder.send(:mystique)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'saves updated definitions in its :stages attribute' do
|
107
|
+
graph_builder.send(:mystique, for_class: String)
|
108
|
+
graph_builder.stages[:mystique].for_class.should == String
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'allows for relabelling of Hanuman::StageBuilders' do
|
112
|
+
graph_builder.send(:mystique, label: :colossus)
|
113
|
+
graph_builder.stages.should include(:colossus)
|
114
|
+
graph_builder.stages.should_not include(:mystique)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context '#show' do
|
119
|
+
it 'shows what is currently registered' do
|
120
|
+
subject.show.should be_a(Hash)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hanuman::Stage, :hanuman => true do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@orig_reg = Hanuman.registry.show
|
7
|
+
Hanuman.registry.clear!
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:each) do
|
11
|
+
Hanuman.registry.clear!
|
12
|
+
Hanuman.registry.merge!(@orig_reg)
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'a class inheriting from Hanuman::Stage' do
|
16
|
+
|
17
|
+
klass = Object.const_set('Gambit', Class.new(Hanuman::Stage))
|
18
|
+
subject{ klass }
|
19
|
+
|
20
|
+
it 'creates its own label' do
|
21
|
+
subject.label.should == :gambit
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'creates its own builder' do
|
25
|
+
subject.builder.should be_instance_of(Hanuman::StageBuilder)
|
26
|
+
subject.builder.for_class.should == subject
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can register its definition' do
|
30
|
+
expect{ subject.register }.to change{ Hanuman.registry.retrieve(:gambit) }.from(nil).to(subject.builder)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'can register itself under a different label' do
|
34
|
+
expect{ subject.register(:wolverine) }.to change{ Hanuman.registry.retrieve(:wolverine) }.from(nil)
|
35
|
+
Hanuman.registry.retrieve(:wolverine).label.should == :wolverine
|
36
|
+
Hanuman.registry.should_not be_registered(:gambit)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe Hanuman::StageBuilder, :hanuman => true do
|
42
|
+
|
43
|
+
it_behaves_like 'a Stage::Builder'
|
44
|
+
|
45
|
+
its(:namespace){ should be(Hanuman::Stage) }
|
46
|
+
|
47
|
+
context '#define' do
|
48
|
+
let(:test_klass){ Object.const_set('Jubilee', Class.new(subject.namespace)) }
|
49
|
+
let(:block_arg) { ->(){ def shoot_fireworks!() ; end } }
|
50
|
+
after(:each) { Object.send(:remove_const, 'Jubilee') }
|
51
|
+
|
52
|
+
context 'with a block' do
|
53
|
+
it 'defines the class which evaluates the block' do
|
54
|
+
subject.for_class = test_klass
|
55
|
+
test_klass.should_receive(:class_eval).with(&block_arg)
|
56
|
+
subject.define(&block_arg)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context '#serialize' do
|
62
|
+
it 'does not serialize its :links attribute' do
|
63
|
+
subject.serialize.should_not include(:links)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context '#into' do
|
68
|
+
subject { described_class.receive(label: :pyro) }
|
69
|
+
let(:other_stage){ described_class.receive(label: :iceman) }
|
70
|
+
|
71
|
+
it 'returns the linked into stage for chaining' do
|
72
|
+
subject.into(other_stage).should be(other_stage)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'links two stages together with a simple link' do
|
76
|
+
subject.into(other_stage)
|
77
|
+
subject.links.should be_any{ |link| link.from == :pyro and link.into == :iceman }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hanuman::Tree do
|
4
|
+
|
5
|
+
include_context "graphs"
|
6
|
+
|
7
|
+
it "iterates over each stage in tree-order" do
|
8
|
+
tree.directed_sort.should == [:first, :second, :third_b, :third_a, :fourth]
|
9
|
+
end
|
10
|
+
|
11
|
+
context "#root" do
|
12
|
+
context "when called without arguments" do
|
13
|
+
it "returns the root of the whole tree" do
|
14
|
+
tree.root.should_not be_nil
|
15
|
+
tree.root.label.should == :first
|
16
|
+
end
|
17
|
+
it "returns the root of a sigle stage tree" do
|
18
|
+
single_stage_tree.root.should_not be_nil
|
19
|
+
single_stage_tree.root.label.should == :first
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
context "when called with a stage" do
|
24
|
+
it "should return the root of the whole tree" do
|
25
|
+
tree.root(tree.stages[:fourth]).should_not be_nil
|
26
|
+
tree.root(tree.stages[:fourth]).label.should == :first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "#ancestor" do
|
32
|
+
it "returns the ancestor of a stage" do
|
33
|
+
tree.ancestor(tree.stages[:fourth]).should_not be_nil
|
34
|
+
tree.ancestor(tree.stages[:fourth]).label.should == :third_a
|
35
|
+
end
|
36
|
+
it "returns nil for the root" do
|
37
|
+
tree.ancestor(tree.root).should be_nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "#leaves" do
|
42
|
+
it "returns the leaf stages of a tree" do
|
43
|
+
tree.leaves.map(&:label).should include(:fourth, :third_b)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns the root of a tree that has no other leaves" do
|
47
|
+
single_stage_tree.leaves.map(&:label).should include(:first)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context "#prepend" do
|
53
|
+
let(:zeroth) { Hanuman::Stage.receive(label: :zeroth) }
|
54
|
+
it "adds the given stage" do
|
55
|
+
expect { tree.prepend(zeroth) }.to change { tree.stages[:zeroth] }.from(nil).to(zeroth)
|
56
|
+
end
|
57
|
+
it "adds a link from the new stage to the old root" do
|
58
|
+
expect { tree.prepend(zeroth) }.to change { tree.has_link?(zeroth, tree.stages[:first]) }.from(false).to(true)
|
59
|
+
end
|
60
|
+
it "the root becomes the new stage" do
|
61
|
+
expect { tree.prepend(zeroth) }.to change { tree.root.label }.from(:first).to(:zeroth)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "#append" do
|
66
|
+
let(:fifth) { Hanuman::Stage.receive(label: :fifth) }
|
67
|
+
it "adds a new stage for each leaf" do
|
68
|
+
expect { tree.append(fifth) }.to change { tree.stages.size }.by(2)
|
69
|
+
end
|
70
|
+
it "adds a link for each of the new stages" do
|
71
|
+
expect { tree.append(fifth) }.to change { tree.links.size }.by(2)
|
72
|
+
end
|
73
|
+
it "but doesn't change the number of leaves " do
|
74
|
+
expect { tree.append(fifth) }.to_not change { tree.leaves.size }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "#add_link" do
|
79
|
+
context "when adding a new stage" do
|
80
|
+
let(:from) { tree.stages[:fourth] }
|
81
|
+
let(:into) { Hanuman::Stage.receive(label: :fifth) }
|
82
|
+
it "adds the new stage to the tree" do
|
83
|
+
expect { tree.add_link(:simple, from, into) }.to change { tree.stages[:fifth] }.from(nil).to(into)
|
84
|
+
end
|
85
|
+
it "adds the new link to the tree" do
|
86
|
+
expect { tree.add_link(:simple, from, into) }.to change { tree.links.size }.by(1)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
context "when adding an existing link" do
|
90
|
+
let(:from) { tree.stages[:third_a] }
|
91
|
+
let(:into) { tree.stages[:fourth] }
|
92
|
+
it "doesn't duplicate the link in the tree" do
|
93
|
+
expect { tree.add_link(:simple, from, into) }.to_not change { tree.links.size }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
context "when adding a link to a stage with an existing parent" do
|
97
|
+
let(:from) { Hanuman::Stage.receive(label: :fifth) }
|
98
|
+
let(:into) { tree.stages[:fourth] }
|
99
|
+
it "raises an error" do
|
100
|
+
expect { tree.add_link(:simple, from, into) }.to raise_error(Hanuman::Tree::MultipleRoots)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
context "when making a cycle" do
|
104
|
+
let(:from) { tree.stages[:fourth] }
|
105
|
+
let(:into) { tree.stages[:first] }
|
106
|
+
it "raises an error" do
|
107
|
+
expect { tree.add_link(:simple, from, into) }.to raise_error(TSort::Cyclic)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
context "when linking a stage to itself" do
|
111
|
+
let(:from) { tree.stages[:fourth] }
|
112
|
+
let(:into) { tree.stages[:fourth] }
|
113
|
+
it "raises an error" do
|
114
|
+
expect { tree.add_link(:simple, from, into) }.to raise_error(TSort::Cyclic)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|