aipp 0.2.5 → 0.2.6
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +8 -0
- data/README.md +40 -14
- data/exe/aip2aixm +1 -1
- data/exe/aip2ofmx +1 -1
- data/lib/aipp.rb +2 -0
- data/lib/aipp/aip.rb +17 -12
- data/lib/aipp/downloader.rb +1 -1
- data/lib/aipp/executable.rb +15 -12
- data/lib/aipp/parser.rb +58 -43
- data/lib/aipp/pdf.rb +1 -1
- data/lib/aipp/regions/LF/AD-1.3.rb +7 -6
- data/lib/aipp/regions/LF/AD-1.6.rb +7 -5
- data/lib/aipp/regions/LF/AD-2.rb +16 -9
- data/lib/aipp/regions/LF/AD-3.1.rb +6 -6
- data/lib/aipp/regions/LF/ENR-2.1.rb +81 -6
- data/lib/aipp/regions/LF/ENR-4.1.rb +3 -1
- data/lib/aipp/regions/LF/ENR-4.3.rb +2 -3
- data/lib/aipp/regions/LF/ENR-5.1.rb +15 -2
- data/lib/aipp/regions/LF/ENR-5.4.rb +90 -0
- data/lib/aipp/regions/LF/ENR-5.5.rb +12 -10
- data/lib/aipp/regions/LF/fixtures/AD-1.3.yml +2 -2
- data/lib/aipp/regions/LF/helpers/base.rb +17 -9
- data/lib/aipp/regions/LF/helpers/radio_AD.rb +21 -13
- data/lib/aipp/t_hash.rb +3 -3
- data/lib/aipp/version.rb +1 -1
- data/lib/core_ext/enumerable.rb +7 -7
- data/lib/core_ext/string.rb +9 -4
- metadata +156 -168
- metadata.gz.sig +1 -0
- data/.github/workflows/test.yml +0 -26
- data/.gitignore +0 -8
- data/.ruby-version +0 -1
- data/.yardopts +0 -3
- data/Guardfile +0 -7
- data/TODO.md +0 -6
- data/aipp.gemspec +0 -45
- data/gems.rb +0 -3
- data/rakefile.rb +0 -12
- data/spec/fixtures/border.geojson +0 -201
- data/spec/fixtures/document.pdf +0 -0
- data/spec/fixtures/document.pdf.json +0 -1
- data/spec/fixtures/new.html +0 -6
- data/spec/fixtures/new.pdf +0 -0
- data/spec/fixtures/new.txt +0 -1
- data/spec/fixtures/source.zip +0 -0
- data/spec/lib/aipp/airac_spec.rb +0 -98
- data/spec/lib/aipp/border_spec.rb +0 -135
- data/spec/lib/aipp/downloader_spec.rb +0 -81
- data/spec/lib/aipp/patcher_spec.rb +0 -46
- data/spec/lib/aipp/pdf_spec.rb +0 -124
- data/spec/lib/aipp/t_hash_spec.rb +0 -44
- data/spec/lib/aipp/version_spec.rb +0 -7
- data/spec/lib/core_ext/enumberable_spec.rb +0 -76
- data/spec/lib/core_ext/hash_spec.rb +0 -27
- data/spec/lib/core_ext/integer_spec.rb +0 -15
- data/spec/lib/core_ext/nil_class_spec.rb +0 -11
- data/spec/lib/core_ext/string_spec.rb +0 -112
- data/spec/sounds/failure.mp3 +0 -0
- data/spec/sounds/success.mp3 +0 -0
- data/spec/spec_helper.rb +0 -29
@@ -1,135 +0,0 @@
|
|
1
|
-
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
describe AIPP::Border::Position do
|
4
|
-
subject do
|
5
|
-
AIPP::Border::Position.new(
|
6
|
-
geometries: [
|
7
|
-
[AIXM.xy(long: 0, lat: 0), AIXM.xy(long: 1, lat: 1), AIXM.xy(long: 2, lat: 2)],
|
8
|
-
[AIXM.xy(long: 10, lat: 10), AIXM.xy(long: 11, lat: 11), AIXM.xy(long: 12, lat: 12)]
|
9
|
-
],
|
10
|
-
geometry_index: 0,
|
11
|
-
coordinates_index: 0
|
12
|
-
)
|
13
|
-
end
|
14
|
-
|
15
|
-
describe :xy do
|
16
|
-
it "returns the coordinates" do
|
17
|
-
_(subject.xy).must_equal AIXM.xy(long: 0, lat: 0)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "returns nil if the geometry index is out of bounds" do
|
21
|
-
_(subject.tap { |s| s.geometry_index = 2 }.xy).must_be_nil
|
22
|
-
end
|
23
|
-
|
24
|
-
it "returns nil if the coordinates index is out of bounds" do
|
25
|
-
_(subject.tap { |s| s.coordinates_index = 3 }.xy).must_be_nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe AIPP::Border do
|
31
|
-
let :fixtures_dir do
|
32
|
-
Pathname(__FILE__).join('..', '..', '..', 'fixtures')
|
33
|
-
end
|
34
|
-
|
35
|
-
# The border.geojson fixture defines three geometries:
|
36
|
-
# * index 0: closed geometry circumventing the airfield of Pujaut
|
37
|
-
# * index 1: closed geometry circumventing the village of Pujaut
|
38
|
-
# * index 2: unclosed I-shaped geometry following the TGV from the S to N bridges over the Rhône
|
39
|
-
# * index 3: unclosed U-shaped geometry around Île de Bartelasse from N to S end of Pont Daladier
|
40
|
-
subject do
|
41
|
-
AIPP::Border.new(fixtures_dir.join('border.geojson'))
|
42
|
-
end
|
43
|
-
|
44
|
-
describe :initialize do
|
45
|
-
it "fails for files unless the extension is .geojson" do
|
46
|
-
_{ AIPP::Border.new("/path/to/another.txt") }.must_raise ArgumentError
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe :name do
|
51
|
-
it "returns the upcased file name" do
|
52
|
-
_(subject.name).must_equal 'BORDER'
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe :closed? do
|
57
|
-
it "returns true for closed geometries" do
|
58
|
-
_(subject.closed?(geometry_index: 0)).must_equal true
|
59
|
-
_(subject.closed?(geometry_index: 1)).must_equal true
|
60
|
-
end
|
61
|
-
|
62
|
-
it "returns false for unclosed geometries" do
|
63
|
-
_(subject.closed?(geometry_index: 2)).must_equal false
|
64
|
-
_(subject.closed?(geometry_index: 3)).must_equal false
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe :nearest do
|
69
|
-
let :point do
|
70
|
-
AIXM.xy(lat: 44.008187986625636, long: 4.759397506713866)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "finds the nearest position on any geometry" do
|
74
|
-
position = subject.nearest(xy: point)
|
75
|
-
_(position.geometry_index).must_equal 1
|
76
|
-
_(position.coordinates_index).must_equal 12
|
77
|
-
_(position.xy).must_equal AIXM.xy(lat: 44.01065725159039, long: 4.760427474975586)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "finds the nearest postition on a given geometry" do
|
81
|
-
position = subject.nearest(xy: point, geometry_index: 0)
|
82
|
-
_(position.geometry_index).must_equal 0
|
83
|
-
_(position.coordinates_index).must_equal 2
|
84
|
-
_(position.xy).must_equal AIXM.xy(lat: 44.00269350325321, long: 4.7519731521606445)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe :segment do
|
89
|
-
it "fails if positions are not on the same geometry" do
|
90
|
-
from_position = AIPP::Border::Position.new(geometries: subject.geometries, geometry_index: 0, coordinates_index: 0)
|
91
|
-
to_position = AIPP::Border::Position.new(geometries: subject.geometries, geometry_index: 1, coordinates_index: 0)
|
92
|
-
_{ subject.segment(from_position: from_position, to_position: to_position) }.must_raise ArgumentError
|
93
|
-
end
|
94
|
-
|
95
|
-
it "returns shortest segment on an unclosed I-shaped geometry" do
|
96
|
-
from_position = subject.nearest(xy: AIXM.xy(lat: 44.002940457248556, long: 4.734249114990234))
|
97
|
-
to_position = subject.nearest(xy: AIXM.xy(lat: 44.07155380033749, long: 4.7687530517578125), geometry_index: from_position.geometry_index)
|
98
|
-
_(subject.segment(from_position: from_position, to_position: to_position)).must_equal [
|
99
|
-
AIXM.xy(lat: 44.00516299694704, long: 4.7371673583984375),
|
100
|
-
AIXM.xy(lat: 44.02195282780904, long: 4.743347167968749),
|
101
|
-
AIXM.xy(lat: 44.037503870182896, long: 4.749870300292969),
|
102
|
-
AIXM.xy(lat: 44.05379106204314, long: 4.755706787109375),
|
103
|
-
AIXM.xy(lat: 44.070073775703484, long: 4.7646331787109375)
|
104
|
-
]
|
105
|
-
end
|
106
|
-
|
107
|
-
it "returns shortest segment on an unclosed U-shaped geometry" do
|
108
|
-
from_position = subject.nearest(xy: AIXM.xy(lat: 43.96563876212758, long: 4.8126983642578125))
|
109
|
-
to_position = subject.nearest(xy: AIXM.xy(lat: 43.956989327857265, long: 4.83123779296875), geometry_index: from_position.geometry_index)
|
110
|
-
_(subject.segment(from_position: from_position, to_position: to_position)).must_equal [
|
111
|
-
AIXM.xy(lat: 43.9646503190861, long: 4.815788269042969),
|
112
|
-
AIXM.xy(lat: 43.98614524381678, long: 4.82025146484375),
|
113
|
-
AIXM.xy(lat: 43.98491011404692, long: 4.840850830078125),
|
114
|
-
AIXM.xy(lat: 43.99479043262446, long: 4.845314025878906),
|
115
|
-
AIXM.xy(lat: 43.98367495857784, long: 4.8538970947265625),
|
116
|
-
AIXM.xy(lat: 43.967121395851485, long: 4.851493835449218),
|
117
|
-
AIXM.xy(lat: 43.96069638244953, long: 4.8442840576171875),
|
118
|
-
AIXM.xy(lat: 43.96069638244953, long: 4.829521179199219)
|
119
|
-
]
|
120
|
-
end
|
121
|
-
|
122
|
-
it "returns shortest segment ignoring endings on a closed geometry" do
|
123
|
-
from_position = subject.nearest(xy: AIXM.xy(lat: 44.00022390676026, long: 4.789009094238281))
|
124
|
-
to_position = subject.nearest(xy: AIXM.xy(lat: 43.99800118202362, long: 4.765834808349609), geometry_index: from_position.geometry_index)
|
125
|
-
_(subject.segment(from_position: from_position, to_position: to_position)).must_equal [
|
126
|
-
AIXM.xy(lat: 44.00077957493397, long: 4.787635803222656),
|
127
|
-
AIXM.xy(lat: 43.99818641226534, long: 4.784030914306641),
|
128
|
-
AIXM.xy(lat: 43.994111213373934, long: 4.78205680847168),
|
129
|
-
AIXM.xy(lat: 44.00115001749186, long: 4.777421951293944),
|
130
|
-
AIXM.xy(lat: 44.002940457248556, long: 4.770212173461914)
|
131
|
-
]
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
describe AIPP::Downloader do
|
4
|
-
let :fixtures_dir do
|
5
|
-
Pathname(__FILE__).join('..', '..', '..', 'fixtures')
|
6
|
-
end
|
7
|
-
|
8
|
-
let :tmp_dir do
|
9
|
-
Pathname(Dir.mktmpdir).tap do |tmp_dir|
|
10
|
-
(sources_dir = tmp_dir.join('sources')).mkpath
|
11
|
-
FileUtils.cp(fixtures_dir.join('source.zip'), sources_dir)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
after do
|
16
|
-
FileUtils.rm_rf(tmp_dir)
|
17
|
-
end
|
18
|
-
|
19
|
-
describe :read do
|
20
|
-
context "source archive does not exist" do
|
21
|
-
it "creates the source archive" do
|
22
|
-
Spy.on(Kernel, open: File.open(fixtures_dir.join('new.html')))
|
23
|
-
subject = AIPP::Downloader.new(storage: tmp_dir, source: 'new-source') do |downloader|
|
24
|
-
_(File.exist?(tmp_dir.join('work'))).must_equal true
|
25
|
-
downloader.read(document: 'new', url: 'http://localhost/new.html')
|
26
|
-
end
|
27
|
-
_(zip_entries(subject.source_file)).must_equal %w(new.html)
|
28
|
-
_(subject.send(:sources_path).children.count).must_equal 2
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "source archive does exist" do
|
33
|
-
it "unzips and uses the source archive" do
|
34
|
-
Spy.on(Kernel, open: File.open(fixtures_dir.join('new.html')))
|
35
|
-
subject = AIPP::Downloader.new(storage: tmp_dir, source: 'source') do |downloader|
|
36
|
-
_(File.exist?(tmp_dir.join('work'))).must_equal true
|
37
|
-
downloader.read(document: 'new', url: 'http://localhost/new.html').tap do |content|
|
38
|
-
_(content).must_be_instance_of Nokogiri::HTML5::Document
|
39
|
-
_(content.text).must_match /fixture-html-new/
|
40
|
-
end
|
41
|
-
end
|
42
|
-
_(zip_entries(subject.source_file)).must_equal %w(new.html one.html two.html)
|
43
|
-
_(subject.send(:sources_path).children.count).must_equal 1
|
44
|
-
end
|
45
|
-
|
46
|
-
it "downloads HTML documents to Nokogiri::HTML5::Document" do
|
47
|
-
Spy.on(Kernel, open: File.open(fixtures_dir.join('new.html')))
|
48
|
-
AIPP::Downloader.new(storage: tmp_dir, source: 'source') do |downloader|
|
49
|
-
downloader.read(document: 'new', url: 'http://localhost/new.html').tap do |content|
|
50
|
-
_(content).must_be_instance_of Nokogiri::HTML5::Document
|
51
|
-
_(content.text).must_match /fixture-html-new/
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
it "downloads and caches PDF documents to AIPP::PDF" do
|
57
|
-
Spy.on(Kernel, open: File.open(fixtures_dir.join('new.pdf')))
|
58
|
-
AIPP::Downloader.new(storage: tmp_dir, source: 'source') do |downloader|
|
59
|
-
downloader.read(document: 'new', url: 'http://localhost/new.pdf').tap do |content|
|
60
|
-
_(content).must_be_instance_of AIPP::PDF
|
61
|
-
_(content.text).must_match /fixture-pdf-new/
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
it "downloads explicitly specified type" do
|
67
|
-
Spy.on(Kernel, open: File.open(fixtures_dir.join('new.pdf')))
|
68
|
-
AIPP::Downloader.new(storage: tmp_dir, source: 'source') do |downloader|
|
69
|
-
downloader.read(document: 'new', url: 'http://localhost/new', type: :pdf).tap do |content|
|
70
|
-
_(content).must_be_instance_of AIPP::PDF
|
71
|
-
_(content.text).must_match /fixture-pdf-new/
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def zip_entries(zip_file)
|
79
|
-
Zip::File.open(zip_file).entries.map(&:name).sort
|
80
|
-
end
|
81
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
class Shoe
|
4
|
-
include AIPP::Patcher
|
5
|
-
|
6
|
-
attr_accessor :size
|
7
|
-
|
8
|
-
patch Shoe, :size do |parser, object, value|
|
9
|
-
case value
|
10
|
-
when 'S' then 36
|
11
|
-
when 'one-size-fits-all' then nil
|
12
|
-
else throw(:abort)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe AIPP::Patcher do
|
18
|
-
subject do
|
19
|
-
Shoe.new.attach_patches
|
20
|
-
end
|
21
|
-
|
22
|
-
context "with patches attached" do
|
23
|
-
after do
|
24
|
-
subject.detach_patches
|
25
|
-
end
|
26
|
-
|
27
|
-
it "overwrites with non-nil values" do
|
28
|
-
_(subject.tap { |s| s.size = 'S' }.size).must_equal 36
|
29
|
-
end
|
30
|
-
|
31
|
-
it "overwrite with nil values" do
|
32
|
-
_(subject.tap { |s| s.size = 'one-size-fits-all' }.size).must_be_nil
|
33
|
-
end
|
34
|
-
|
35
|
-
it "skips overwrite if abort is thrown" do
|
36
|
-
_(subject.tap { |s| s.size = 42 }.size).must_equal 42
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context "with patches detached" do
|
41
|
-
it "removes patches" do
|
42
|
-
subject.detach_patches
|
43
|
-
_(subject.tap { |s| s.size = 'S' }.size).must_equal 'S'
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
data/spec/lib/aipp/pdf_spec.rb
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
describe AIPP::PDF do
|
4
|
-
let :fixtures_dir do
|
5
|
-
Pathname(__FILE__).join('..', '..', '..', 'fixtures')
|
6
|
-
end
|
7
|
-
|
8
|
-
subject do
|
9
|
-
AIPP::PDF.new(fixtures_dir.join('document.pdf'))
|
10
|
-
end
|
11
|
-
|
12
|
-
describe :@page_ranges do
|
13
|
-
it "returns an array of page end positions" do
|
14
|
-
_(subject.instance_variable_get(:@page_ranges)).must_equal [74, 149, 225]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe :page_for do
|
19
|
-
it "finds the page for any given position" do
|
20
|
-
_(subject.send(:page_for, index: 0)).must_equal 1
|
21
|
-
_(subject.send(:page_for, index: 50)).must_equal 1
|
22
|
-
_(subject.send(:page_for, index: 74)).must_equal 1
|
23
|
-
_(subject.send(:page_for, index: 75)).must_equal 2
|
24
|
-
_(subject.send(:page_for, index: 149)).must_equal 2
|
25
|
-
_(subject.send(:page_for, index: 150)).must_equal 3
|
26
|
-
_(subject.send(:page_for, index: 223)).must_equal 3
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe :from do
|
31
|
-
it "fences beginning to any position" do
|
32
|
-
_(subject.from(100).range).must_equal (100..223)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "fences beginning to first existing position" do
|
36
|
-
_(subject.from(:begin).range).must_equal (0..223)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe :to do
|
41
|
-
it "fences beginning to any position" do
|
42
|
-
_(subject.to(100).range).must_equal (0..100)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "fences beginning to first existing position" do
|
46
|
-
_(subject.to(:end).range).must_equal (0..223)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context "without boundaries" do
|
51
|
-
describe :text do
|
52
|
-
it "returns the entire text" do
|
53
|
-
_(subject.text).must_match /\Apage 1, line 1/
|
54
|
-
_(subject.text).must_match /page 3, line 5\z/
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe :each_line do
|
59
|
-
it "maps lines to positions" do
|
60
|
-
target = [
|
61
|
-
["page 1, line 1\n", 1, false],
|
62
|
-
["page 1, line 2\n", 1, false],
|
63
|
-
["page 1, line 3\n", 1, false],
|
64
|
-
["page 1, line 4\n", 1, false],
|
65
|
-
["page 1, line 5\f", 1, false],
|
66
|
-
["page 2, line 1\n", 2, false],
|
67
|
-
["page 2, line 2\n", 2, false],
|
68
|
-
["page 2, line 3\n", 2, false],
|
69
|
-
["page 2, line 4\n", 2, false],
|
70
|
-
["page 2, line 5\f", 2, false],
|
71
|
-
["page 3, line 1\n", 3, false],
|
72
|
-
["page 3, line 2\n", 3, false],
|
73
|
-
["page 3, line 3\n", 3, false],
|
74
|
-
["page 3, line 4\n", 3, false],
|
75
|
-
["page 3, line 5", 3, true]
|
76
|
-
]
|
77
|
-
subject.each_line do |line, page, last|
|
78
|
-
target_line, target_page, target_last = target.shift
|
79
|
-
_(line).must_equal target_line
|
80
|
-
_(page).must_equal target_page
|
81
|
-
_(last).must_equal target_last
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
it "returns an enumerator if no block is given" do
|
86
|
-
_(subject.each_line).must_be_instance_of Enumerator
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
context "with boundaries" do
|
92
|
-
before do
|
93
|
-
subject.from(100).to(200)
|
94
|
-
end
|
95
|
-
|
96
|
-
describe :text do
|
97
|
-
it "returns the entire text" do
|
98
|
-
_(subject.text).must_match /\Ane 2/
|
99
|
-
_(subject.text).must_match /page 3\z/
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
describe :each_line do
|
104
|
-
it "maps lines to positions" do
|
105
|
-
target = [
|
106
|
-
["ne 2\n", 2, false],
|
107
|
-
["page 2, line 3\n", 2, false],
|
108
|
-
["page 2, line 4\n", 2, false],
|
109
|
-
["page 2, line 5\f", 2, false],
|
110
|
-
["page 3, line 1\n", 3, false],
|
111
|
-
["page 3, line 2\n", 3, false],
|
112
|
-
["page 3, line 3\n", 3, false],
|
113
|
-
["page 3", 3, true]
|
114
|
-
]
|
115
|
-
subject.each_line do |line, page, last|
|
116
|
-
target_line, target_page, target_last = target.shift
|
117
|
-
_(line).must_equal target_line
|
118
|
-
_(page).must_equal target_page
|
119
|
-
_(last).must_equal target_last
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
describe AIPP::THash do
|
4
|
-
context "non-circular dependencies" do
|
5
|
-
subject do
|
6
|
-
AIPP::THash[
|
7
|
-
dns: %i(net),
|
8
|
-
webserver: %i(dns logger),
|
9
|
-
net: [],
|
10
|
-
logger: []
|
11
|
-
]
|
12
|
-
end
|
13
|
-
|
14
|
-
describe :tsort do
|
15
|
-
it "must compile the overall dependency list" do
|
16
|
-
_(subject.tsort).must_equal %i(net dns logger webserver)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "must compile partial dependency lists" do
|
20
|
-
_(subject.tsort(:dns)).must_equal %i(net dns)
|
21
|
-
_(subject.tsort(:logger)).must_equal %i(logger)
|
22
|
-
_(subject.tsort(:webserver)).must_equal %i(net dns logger webserver)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context "circular dependencies" do
|
28
|
-
subject do
|
29
|
-
AIPP::THash[
|
30
|
-
dns: %i(net),
|
31
|
-
webserver: %i(dns logger),
|
32
|
-
net: %i(dns),
|
33
|
-
logger: []
|
34
|
-
]
|
35
|
-
end
|
36
|
-
|
37
|
-
describe :tsort do
|
38
|
-
it "must raise cyclic dependency error" do
|
39
|
-
_{ subject.tsort }.must_raise TSort::Cyclic
|
40
|
-
_{ subject.tsort(:dns) }.must_raise TSort::Cyclic
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
describe Enumerable do
|
4
|
-
|
5
|
-
describe :split do
|
6
|
-
context "by object" do
|
7
|
-
it "must split at matching element" do
|
8
|
-
_([1, 2, 0, 3, 4].split(0)).must_equal [[1, 2], [3, 4]]
|
9
|
-
end
|
10
|
-
|
11
|
-
it "won't split when no element matches" do
|
12
|
-
_([1, 2, 3].split(0)).must_equal [[1, 2, 3]]
|
13
|
-
end
|
14
|
-
|
15
|
-
it "won't split zero length enumerable" do
|
16
|
-
_([].split(0)).must_equal []
|
17
|
-
end
|
18
|
-
|
19
|
-
it "must keep leading empty subarrays" do
|
20
|
-
_([0, 1, 2, 0, 3, 4].split(0)).must_equal [[], [1, 2], [3, 4]]
|
21
|
-
end
|
22
|
-
|
23
|
-
it "must keep empty subarrays in the middle" do
|
24
|
-
_([1, 2, 0, 0, 3, 4].split(0)).must_equal [[1, 2], [], [3, 4]]
|
25
|
-
end
|
26
|
-
|
27
|
-
it "must drop trailing empty subarrays" do
|
28
|
-
_([1, 2, 0, 3, 4, 0].split(0)).must_equal [[1, 2], [3, 4]]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "by block" do
|
33
|
-
it "must split at matching element" do
|
34
|
-
_([1, 2, 0, 3, 4].split { |e| e.zero? }).must_equal [[1, 2], [3, 4]]
|
35
|
-
end
|
36
|
-
|
37
|
-
it "won't split when no element matches" do
|
38
|
-
_([1, 2, 3].split { |e| e.zero? }).must_equal [[1, 2, 3]]
|
39
|
-
end
|
40
|
-
|
41
|
-
it "won't split zero length enumerable" do
|
42
|
-
_([].split { |e| e.zero? }).must_equal []
|
43
|
-
end
|
44
|
-
|
45
|
-
it "must keep leading empty subarrays" do
|
46
|
-
_([0, 1, 2, 0, 3, 4].split { |e| e.zero? }).must_equal [[], [1, 2], [3, 4]]
|
47
|
-
end
|
48
|
-
|
49
|
-
it "must keep empty subarrays in the middle" do
|
50
|
-
_([1, 2, 0, 0, 3, 4].split { |e| e.zero? }).must_equal [[1, 2], [], [3, 4]]
|
51
|
-
end
|
52
|
-
|
53
|
-
it "must drop trailing empty subarrays" do
|
54
|
-
_([1, 2, 0, 3, 4, 0].split { |e| e.zero? }).must_equal [[1, 2], [3, 4]]
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe :group_by_chunks do
|
60
|
-
it "fails to group if the first element does not meet the chunk condition" do
|
61
|
-
subject = [10, 11, 12, 2, 20, 21 ]
|
62
|
-
_{ subject.group_by_chunks { |i| i < 10 } }.must_raise ArgumentError
|
63
|
-
end
|
64
|
-
|
65
|
-
it "must map matching elements to array of subsequent non-matching elements" do
|
66
|
-
subject = [1, 10, 11, 12, 2, 20, 21, 3, 30, 31, 32]
|
67
|
-
_(subject.group_by_chunks { |i| i < 10 }).must_equal(1 => [10, 11, 12], 2 => [20, 21], 3 => [30, 31, 32])
|
68
|
-
end
|
69
|
-
|
70
|
-
it "must map matching elements to empty array if no subsequent non-matching elements exist" do
|
71
|
-
subject = [1, 10, 11, 12, 2, 3, 30]
|
72
|
-
_(subject.group_by_chunks { |i| i < 10 }).must_equal(1 => [10, 11, 12], 2 => [], 3 => [30])
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|