fat_core 0.0.1

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.
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kernel do
4
+ it "should know how to time a block of code" do
5
+ result = time_it "do something" do
6
+ (1..10_000_000).each { |k| k * k }
7
+ "hello"
8
+ end
9
+ expect(result).to eq('hello')
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ require File.dirname(File.absolute_path(__FILE__)) + '/../spec_helper.rb'
2
+
3
+ describe Numeric do
4
+ it "should properly round up" do
5
+ 236.5555.commas(2).should == '236.56'
6
+ -236.5555.commas(2).should == '-236.56'
7
+ end
8
+
9
+ it "should properly round down" do
10
+ 236.5512.commas(2).should == '236.55'
11
+ -236.5512.commas(2).should == '-236.55'
12
+ end
13
+
14
+ it "should place commas properly" do
15
+ 123456789.0123.commas(2).should == '123,456,789.01'
16
+ -123456789.0123.commas(2).should == '-123,456,789.01'
17
+ end
18
+
19
+ it "should place commas properly with no fraction" do
20
+ 123456789.commas.should == '123,456,789'
21
+ -123456789.commas.should == '-123,456,789'
22
+ end
23
+
24
+ it "should not place commas in a number with exponent" do
25
+ 123456.789e100.commas.should == '1.23456789e+105'
26
+ end
27
+
28
+ it "should be able to convert itself into an H:M:S string" do
29
+ expect(60.secs_to_hms).to eq('00:01:00')
30
+ expect(120.secs_to_hms).to eq('00:02:00')
31
+ expect(6584.secs_to_hms).to eq('01:49:44')
32
+ expect(6584.35.secs_to_hms).to eq('01:49:44.35')
33
+ end
34
+ end
@@ -0,0 +1,294 @@
1
+ require 'spec_helper'
2
+
3
+ describe Period do
4
+ before :each do
5
+ # Pretend it is this date. Not at beg or end of year, quarter,
6
+ # month, or week. It is a Wednesday
7
+ Date.stub(:today).and_return(Date.parse('2012-07-18'))
8
+ @test_today = Date.parse('2012-07-18')
9
+ end
10
+
11
+ describe "initialization" do
12
+
13
+ it "should be initializable with date strings" do
14
+ Period.new('2013-01-01', '2013-12-13').should be_instance_of Period
15
+ end
16
+
17
+ it "should be initializable with Dates" do
18
+ Period.new(Date.parse('2013-01-01'), Date.parse('2013-12-13')).
19
+ should be_instance_of Period
20
+ end
21
+
22
+ it "should raise a ArgumentError if last > first" do
23
+ expect {
24
+ Period.new('2013-01-01', '2012-12-31')
25
+ }.to raise_error ArgumentError
26
+ end
27
+
28
+ it "should raise a ArgumentError if initialized with invalid date string" do
29
+ expect {
30
+ Period.new('2013-01-01', '2013-12-32')
31
+ }.to raise_error ArgumentError
32
+ expect {
33
+ Period.new('2013-13-01', '2013-12-31')
34
+ }.to raise_error ArgumentError
35
+ end
36
+
37
+ it "should raise a ArgumentError if initialized otherwise" do
38
+ expect {
39
+ Period.new(2013-01-01, 2013-12-31)
40
+ }.to raise_error ArgumentError
41
+ end
42
+ end
43
+
44
+ describe "class methods" do
45
+
46
+ it "should know the days in a chunk sym" do
47
+ Period.chunk_sym_to_days(:year).should eq(365)
48
+ Period.chunk_sym_to_days(:quarter).should eq(90)
49
+ Period.chunk_sym_to_days(:bimonth).should eq(60)
50
+ Period.chunk_sym_to_days(:month).should eq(30)
51
+ Period.chunk_sym_to_days(:semimonth).should eq(15)
52
+ Period.chunk_sym_to_days(:biweek).should eq(14)
53
+ Period.chunk_sym_to_days(:week).should eq(7)
54
+ Period.chunk_sym_to_days(:day).should eq(1)
55
+ Period.chunk_sym_to_days(:irregular).should eq(30)
56
+ expect {
57
+ Period.chunk_sym_to_days(:eon)
58
+ }.to raise_error ArgumentError
59
+ end
60
+
61
+ it "should know the chunk sym for given days but only :year, :quarter, :month" do
62
+ (356..376).each { |d| Period.days_to_chunk_sym(d).should eq(:year) }
63
+ (86..96).each { |d| Period.days_to_chunk_sym(d).should eq(:quarter) }
64
+ (28..31).each { |d| Period.days_to_chunk_sym(d).should eq(:month) }
65
+ Period.days_to_chunk_sym(7).should eq(:week)
66
+ Period.days_to_chunk_sym(1).should eq(:day)
67
+ end
68
+
69
+ it "should know what to call a chunk based on its size" do
70
+ expect(Period.new('2011-01-01', '2011-12-31').chunk_name).to eq('Year')
71
+ expect(Period.new('2011-01-01', '2011-03-31').chunk_name).to eq('Quarter')
72
+ expect(Period.new('2011-01-01', '2011-01-31').chunk_name).to eq('Month')
73
+ expect(Period.new('2011-01-01', '2011-01-07').chunk_name).to eq('Week')
74
+ expect(Period.new('2011-01-01', '2011-01-01').chunk_name).to eq('Day')
75
+ expect(Period.new('2011-01-01', '2011-01-21').chunk_name).to eq('Period')
76
+ # Only size matters, not whether the period begins and ends on
77
+ # calendar unit boundaries.
78
+ expect(Period.new('2011-02-11', '2011-03-10').chunk_name).to eq('Month')
79
+ end
80
+ end
81
+
82
+ describe "instance methods" do
83
+
84
+ it "should be able to compare for equality" do
85
+ pp1 = Period.new('2013-01-01', '2013-12-31')
86
+ pp2 = Period.new('2013-01-01', '2013-12-31')
87
+ pp3 = Period.new('2013-01-01', '2013-12-30')
88
+ (pp1 == pp2).should be_true
89
+ (pp1 == pp3).should_not be_true
90
+ end
91
+
92
+ it "should be able to convert into a Range" do
93
+ pp = Period.new('2013-01-01', '2013-12-31')
94
+ rr = Period.new('2013-01-01', '2013-12-31').to_range
95
+ rr.should be_instance_of Range
96
+ rr.first.should eq(pp.first)
97
+ rr.first.should eq(pp.first)
98
+ end
99
+
100
+ it "should be able to tell if it contains a date" do
101
+ pp = Period.new('2013-01-01', '2013-12-31')
102
+ pp.contains?(Date.parse('2013-01-01')).should be_true
103
+ pp.contains?(Date.parse('2013-07-04')).should be_true
104
+ pp.contains?(Date.parse('2013-12-31')).should be_true
105
+ pp.contains?(Date.parse('2012-07-04')).should be_false
106
+ end
107
+
108
+ it "should be able to make a concise period string" do
109
+ Period.new('2013-01-01', '2013-12-31').to_s.
110
+ should eq('2013')
111
+ Period.new('2013-04-01', '2013-06-30').to_s.
112
+ should eq('2013-2Q')
113
+ Period.new('2013-03-01', '2013-03-31').to_s.
114
+ should eq('2013-03')
115
+ Period.new('2013-03-11', '2013-10-31').to_s.
116
+ should eq('2013-03-11 to 2013-10-31')
117
+ end
118
+
119
+ # Note in the following that first period must begin within self.
120
+ it "should be able to chunk into years" do
121
+ chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :year)
122
+ chunks.size.should eq(3)
123
+ chunks[0].first.iso.should eq('2010-01-01')
124
+ chunks[0].last.iso.should eq('2010-12-31')
125
+ chunks[1].first.iso.should eq('2011-01-01')
126
+ chunks[1].last.iso.should eq('2011-12-31')
127
+ chunks[2].first.iso.should eq('2012-01-01')
128
+ chunks[2].last.iso.should eq('2012-12-31')
129
+ end
130
+
131
+ it "should be able to chunk into quarters" do
132
+ chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :quarter)
133
+ chunks.size.should eq(12)
134
+ chunks[0].first.iso.should eq('2010-01-01')
135
+ chunks[0].last.iso.should eq('2010-03-31')
136
+ chunks[1].first.iso.should eq('2010-04-01')
137
+ chunks[1].last.iso.should eq('2010-06-30')
138
+ chunks[2].first.iso.should eq('2010-07-01')
139
+ chunks[2].last.iso.should eq('2010-09-30')
140
+ chunks.last.first.iso.should eq('2012-10-01')
141
+ chunks.last.last.iso.should eq('2012-12-31')
142
+ end
143
+
144
+ it "should be able to chunk into bimonths" do
145
+ chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :bimonth)
146
+ chunks.size.should eq(18)
147
+ chunks[0].first.iso.should eq('2010-01-01')
148
+ chunks[0].last.iso.should eq('2010-02-28')
149
+ chunks[1].first.iso.should eq('2010-03-01')
150
+ chunks[1].last.iso.should eq('2010-04-30')
151
+ chunks[2].first.iso.should eq('2010-05-01')
152
+ chunks[2].last.iso.should eq('2010-06-30')
153
+ chunks.last.first.iso.should eq('2012-11-01')
154
+ chunks.last.last.iso.should eq('2012-12-31')
155
+ end
156
+
157
+ it "should be able to chunk into months" do
158
+ chunks = Period.new('2009-12-15', '2013-01-10').chunks(size: :month)
159
+ chunks.size.should eq(36)
160
+ chunks[0].first.iso.should eq('2010-01-01')
161
+ chunks[0].last.iso.should eq('2010-01-31')
162
+ chunks[1].first.iso.should eq('2010-02-01')
163
+ chunks[1].last.iso.should eq('2010-02-28')
164
+ chunks[2].first.iso.should eq('2010-03-01')
165
+ chunks[2].last.iso.should eq('2010-03-31')
166
+ chunks.last.first.iso.should eq('2012-12-01')
167
+ chunks.last.last.iso.should eq('2012-12-31')
168
+ end
169
+
170
+ it "should be able to chunk into semimonths" do
171
+ chunks = Period.new('2009-12-25', '2013-01-10').chunks(size: :semimonth)
172
+ chunks.size.should eq(72)
173
+ chunks[0].first.iso.should eq('2010-01-01')
174
+ chunks[0].last.iso.should eq('2010-01-15')
175
+ chunks[1].first.iso.should eq('2010-01-16')
176
+ chunks[1].last.iso.should eq('2010-01-31')
177
+ chunks[2].first.iso.should eq('2010-02-01')
178
+ chunks[2].last.iso.should eq('2010-02-15')
179
+ chunks.last.first.iso.should eq('2012-12-16')
180
+ chunks.last.last.iso.should eq('2012-12-31')
181
+ end
182
+
183
+ it "should be able to chunk into biweeks" do
184
+ chunks = Period.new('2009-12-29', '2013-01-10').chunks(size: :biweek)
185
+ expect(chunks.size).to be >=(26*3)
186
+ chunks[0].first.iso.should eq('2010-01-04')
187
+ chunks[0].last.iso.should eq('2010-01-17')
188
+ chunks[1].first.iso.should eq('2010-01-18')
189
+ chunks[1].last.iso.should eq('2010-01-31')
190
+ chunks[2].first.iso.should eq('2010-02-01')
191
+ chunks[2].last.iso.should eq('2010-02-14')
192
+ chunks.last.first.iso.should eq('2012-12-17')
193
+ chunks.last.last.iso.should eq('2012-12-30')
194
+ end
195
+
196
+ it "should be able to chunk into weeks" do
197
+ chunks = Period.new('2010-01-01', '2012-12-31').chunks(size: :week)
198
+ expect(chunks.size).to be >=(52*3)
199
+ chunks[0].first.iso.should eq('2010-01-04')
200
+ chunks[0].last.iso.should eq('2010-01-10')
201
+ chunks[1].first.iso.should eq('2010-01-11')
202
+ chunks[1].last.iso.should eq('2010-01-17')
203
+ chunks[2].first.iso.should eq('2010-01-18')
204
+ chunks[2].last.iso.should eq('2010-01-24')
205
+ chunks.last.first.iso.should eq('2012-12-24')
206
+ chunks.last.last.iso.should eq('2012-12-30')
207
+ end
208
+
209
+ it "should be able to chunk into days" do
210
+ chunks = Period.new('2012-12-28', '2012-12-31').chunks(size: :day)
211
+ chunks.size.should eq(4)
212
+ chunks[0].first.iso.should eq('2012-12-28')
213
+ chunks[0].last.iso.should eq('2012-12-28')
214
+ chunks[1].first.iso.should eq('2012-12-29')
215
+ chunks[1].last.iso.should eq('2012-12-29')
216
+ chunks[2].first.iso.should eq('2012-12-30')
217
+ chunks[2].last.iso.should eq('2012-12-30')
218
+ chunks.last.first.iso.should eq('2012-12-31')
219
+ chunks.last.last.iso.should eq('2012-12-31')
220
+ end
221
+
222
+ it "should not include a partial final chunk by default" do
223
+ chunks = Period.new('2012-01-01', '2012-03-30').chunks(size: :month)
224
+ chunks.size.should eq(2)
225
+ end
226
+
227
+ it "should include a partial final chunk if partial_last" do
228
+ chunks = Period.new('2012-01-01', '2012-03-30').
229
+ chunks(size: :month, partial_last: true)
230
+ chunks.size.should eq(3)
231
+ chunks.last.first.should eq(Date.parse('2012-03-01'))
232
+ chunks.last.last.should eq(Date.parse('2012-03-30'))
233
+ end
234
+
235
+ it "should include a final chunk beyond end_date if round_up" do
236
+ chunks = Period.new('2012-01-01', '2012-03-30').
237
+ chunks(size: :month, round_up_last: true)
238
+ chunks.size.should eq(3)
239
+ chunks.last.first.should eq(Date.parse('2012-03-01'))
240
+ chunks.last.last.should eq(Date.parse('2012-03-31'))
241
+ end
242
+
243
+ it "should not include a partial initial chunk by default" do
244
+ chunks = Period.new('2012-01-13', '2012-03-31').chunks(size: :month)
245
+ chunks.size.should eq(2)
246
+ chunks[0].first.should eq(Date.parse('2012-02-01'))
247
+ chunks[0].last.should eq(Date.parse('2012-02-29'))
248
+ end
249
+
250
+ it "should include a partial initial chunk by if partial_first" do
251
+ chunks = Period.new('2012-01-13', '2012-03-31').
252
+ chunks(size: :month, partial_first: true)
253
+ chunks.size.should eq(3)
254
+ chunks[0].first.should eq(Date.parse('2012-01-13'))
255
+ chunks[0].last.should eq(Date.parse('2012-01-31'))
256
+ end
257
+
258
+ it "should include a final chunk beyond end_date if round_up" do
259
+ chunks = Period.new('2012-01-01', '2012-03-30').
260
+ chunks(size: :month, round_up_last: true)
261
+ chunks.size.should eq(3)
262
+ chunks.last.first.should eq(Date.parse('2012-03-01'))
263
+ chunks.last.last.should eq(Date.parse('2012-03-31'))
264
+ end
265
+
266
+ it "should be able to its chunk_sym" do
267
+ Period.new('2013-01-01', '2013-12-31').chunk_sym.should eq(:year)
268
+ Period.new('2012-01-01', '2013-12-31').chunk_sym.should_not eq(:year)
269
+
270
+ Period.new('2013-04-01', '2013-06-30').chunk_sym.should eq(:quarter)
271
+ Period.new('2013-04-01', '2013-09-30').chunk_sym.should_not eq(:quarter)
272
+
273
+ Period.new('2013-03-01', '2013-04-30').chunk_sym.should eq(:bimonth)
274
+ Period.new('2013-03-01', '2013-06-30').chunk_sym.should_not eq(:bimonth)
275
+
276
+ Period.new('2013-04-01', '2013-04-30').chunk_sym.should eq(:month)
277
+ Period.new('2013-04-01', '2013-05-30').chunk_sym.should_not eq(:month)
278
+
279
+ Period.new('2013-05-16', '2013-05-31').chunk_sym.should eq(:semimonth)
280
+ Period.new('2013-05-16', '2013-06-30').chunk_sym.should_not eq(:semimonth)
281
+
282
+ Period.new('2013-11-04', '2013-11-17').chunk_sym.should eq(:biweek)
283
+ Period.new('2013-11-04', '2013-11-24').chunk_sym.should_not eq(:biweek)
284
+
285
+ Period.new('2013-11-11', '2013-11-17').chunk_sym.should eq(:week)
286
+ Period.new('2013-11-11', '2013-11-24').chunk_sym.should_not eq(:week)
287
+
288
+ Period.new('2013-11-10', '2013-11-10').chunk_sym.should eq(:day)
289
+ Period.new('2013-11-10', '2013-11-11').chunk_sym.should_not eq(:day)
290
+
291
+ Period.new('2013-11-02', '2013-12-16').chunk_sym.should eq(:irregular)
292
+ end
293
+ end
294
+ end
@@ -0,0 +1,246 @@
1
+ require File.dirname(File.absolute_path(__FILE__)) + '/../spec_helper.rb'
2
+
3
+ describe Range do
4
+ describe "set operations" do
5
+ it "should know if it is a subset of another range" do
6
+ expect((4..8)).to be_subset_of((2..9))
7
+ expect((4..8)).to be_subset_of((4..8))
8
+ expect((4..8)).not_to be_subset_of((2..7))
9
+ expect((4..8)).not_to be_subset_of((5..8))
10
+ expect((4..8)).not_to be_subset_of((11..20))
11
+ end
12
+
13
+ it "should know if it is a proper subset of another range" do
14
+ expect((4..8)).to be_proper_subset_of((2..9))
15
+ expect((4..8)).not_to be_proper_subset_of((4..8))
16
+ expect((4..8)).not_to be_proper_subset_of((2..7))
17
+ expect((4..8)).not_to be_proper_subset_of((5..8))
18
+ expect((4..8)).not_to be_proper_subset_of((11..20))
19
+ end
20
+
21
+ it "should know if it is a superset of another range" do
22
+ expect((4..8)).to be_superset_of((5..7))
23
+ expect((4..8)).to be_superset_of((6..8))
24
+ expect((4..8)).to be_superset_of((4..7))
25
+ expect((4..8)).to be_superset_of((4..8))
26
+ expect((4..8)).not_to be_superset_of((2..9))
27
+ expect((4..8)).not_to be_superset_of((2..8))
28
+ expect((4..8)).not_to be_superset_of((4..9))
29
+ expect((4..8)).not_to be_superset_of((8..20))
30
+ expect((4..8)).not_to be_superset_of((0..4))
31
+ expect((4..8)).not_to be_superset_of((0..3))
32
+ expect((4..8)).not_to be_superset_of((9..20))
33
+ end
34
+
35
+ it "should know if it is a superset of another range" do
36
+ expect((4..8)).to be_proper_superset_of((5..7))
37
+ expect((4..8)).not_to be_proper_superset_of((6..8))
38
+ expect((4..8)).not_to be_proper_superset_of((4..7))
39
+ expect((4..8)).not_to be_proper_superset_of((4..8))
40
+ expect((4..8)).not_to be_proper_superset_of((2..9))
41
+ expect((4..8)).not_to be_proper_superset_of((2..8))
42
+ expect((4..8)).not_to be_proper_superset_of((4..9))
43
+ expect((4..8)).not_to be_proper_superset_of((8..20))
44
+ expect((4..8)).not_to be_proper_superset_of((0..4))
45
+ expect((4..8)).not_to be_proper_superset_of((0..3))
46
+ expect((4..8)).not_to be_proper_superset_of((9..20))
47
+ end
48
+
49
+ it "should know its intersection with another range" do
50
+ ((0..10) & (5..20)).should eq((5..10))
51
+ ((0..10) & (5..20)).should eq((5..20) & (0..10))
52
+ ((0..10) & (10..20)).should eq((10..10))
53
+ end
54
+
55
+ it "intersection should return nil if there is no overlap" do
56
+ ((0..10) & (15..20)).should be_nil
57
+ end
58
+
59
+ it "should know its union with another range" do
60
+ ((0..10) + (5..20)).should eq((0..20))
61
+ ((0..10) + (5..20)).should eq((5..20) + (0..10))
62
+ ((0..10) + (10..20)).should eq((0..20))
63
+ end
64
+
65
+ it "union should return nil if there is no overlap" do
66
+ ((0..10) & (15..20)).should be_nil
67
+ end
68
+
69
+ it "should know the difference with another range" do
70
+ # Other is same as self
71
+ expect(((4..10) - (4..10)).size).to eq(0)
72
+ expect(((4..10) - (4..10))).to be_empty
73
+
74
+ # Other is proper subset of self
75
+ expect(((4..10) - (6..7)).first).to eq((4..5))
76
+ expect(((4..10) - (6..7)).last).to eq((8..10))
77
+ expect(((4..10) - (6..10)).first).to eq((4..5))
78
+ expect(((4..10) - (4..7)).last).to eq((8..10))
79
+
80
+ # Other overlaps on the left
81
+ expect(((4..10) - (0..6)).size).to eq(1)
82
+ expect(((4..10) - (0..6)).first).to eq((7..10))
83
+
84
+ expect(((4..10) - (4..6)).size).to eq(1)
85
+ expect(((4..10) - (4..6)).first).to eq((7..10))
86
+
87
+ # Other overlaps on the right
88
+ expect(((4..10) - (7..11)).size).to eq(1)
89
+ expect(((4..10) - (7..11)).first).to eq((4..6))
90
+
91
+ expect(((4..10) - (7..10)).size).to eq(1)
92
+ expect(((4..10) - (7..10)).last).to eq((4..6))
93
+
94
+ # Other does not overlap
95
+ expect((4..10) - (13..20)).to be_empty
96
+ expect((4..10) - (1..3)).to be_empty
97
+ end
98
+ end
99
+
100
+ describe "joining" do
101
+ it "should be able to join contiguous ranges" do
102
+ (0..3).join(4..8).should == (0..8)
103
+ end
104
+
105
+ it "should return nil on join of non-contiguous ranges" do
106
+ (0..3).join(5..8).should be_nil
107
+ (0...3).join(4..8).should be_nil
108
+ end
109
+
110
+ it "should work with Floats, allowing single-point overlap" do
111
+ (0.0..3.0).join(3.0..8.2).should == (0.0..8.2)
112
+ end
113
+ end
114
+
115
+ describe "spanning" do
116
+ it "should be able to determine whether it is spanned by a set of ranges" do
117
+ (0..10).should be_spanned_by([(0..3), (4..6), (7..10)])
118
+ end
119
+
120
+ it "should be determine that overlapping ranges do not span" do
121
+ (0..10).should_not be_spanned_by([(0..3), (3..6), (7..10)])
122
+ end
123
+
124
+ it "should allow spanning ranges to be any Enumerable" do
125
+ require 'set'
126
+ set = [(0..3), (4..6), (7..10)].to_set
127
+ (0..10).should be_spanned_by(set)
128
+ set = [(0...3), (4..6), (7..10)].to_set
129
+ (0..10).should_not be_spanned_by(set)
130
+ end
131
+
132
+ it "should allow the spanning set to be wider than itself" do
133
+ set = [(0..3), (4..6), (7..10)].to_set
134
+ (2..8).should be_spanned_by(set)
135
+ (5..6).should be_spanned_by(set)
136
+ end
137
+ end
138
+
139
+ describe "overlapping a single range" do
140
+ it "should know if another range overlaps it" do
141
+ (0..10).overlaps?(-3..5).should be_true
142
+ (0..10).overlaps?(3..5).should be_true
143
+ (0..10).overlaps?(8..15).should be_true
144
+ (0..10).overlaps?(0..10).should be_true
145
+ (0..10).overlaps?(11..12).should be_false
146
+ (0..10).overlaps?(-11..-1).should be_false
147
+ end
148
+
149
+ it "should be able to determine whether a set contains covered overlaps" do
150
+ (0..10).should have_overlaps_within([(0..3), (2..6), (7..10)])
151
+ end
152
+
153
+ it "should not care about overlaps outside range" do
154
+ (11..15).should_not have_overlaps_within([(0..3), (2..6), (7..10)])
155
+ end
156
+
157
+ it "should not count contiguous ranges as overlapping" do
158
+ (0..10).should_not have_overlaps_within([(0..3), (4..6), (7..10)])
159
+ end
160
+
161
+ it "should not count non-contiguous ranges as overlapping" do
162
+ (0..10).should_not have_overlaps_within([(0..3), (4..6), (8..10)])
163
+ end
164
+
165
+ it "should not count an empty set as overlapping" do
166
+ (0..10).should_not have_overlaps_within([])
167
+ end
168
+ end
169
+
170
+ describe "coverage gaps" do
171
+ it "should return an empty array if ranges completely cover" do
172
+ (0..10).gaps([(-1..3), (4..8), (9..11)]).should be_empty
173
+ end
174
+
175
+ it "should return array for itself if ranges are empty" do
176
+ (0..10).gaps([]).should eq([(0..10)])
177
+ end
178
+
179
+ it "should return an array of gaps" do
180
+ gaps = (0..10).gaps([(0..3), (5..6), (9..10)])
181
+ gaps[0].should eq((4..4))
182
+ gaps[1].should eq((7..8))
183
+ end
184
+
185
+ it "should allow ranges to extend before and after self" do
186
+ gaps = (0..10).gaps([(-3..3), (4..6), (7..13)])
187
+ gaps.should be_empty
188
+ end
189
+
190
+ it "should return an gaps at beginning and end" do
191
+ gaps = (0..10).gaps([(2..3), (4..6), (7..8)])
192
+ gaps[0].should eq((0..1))
193
+ gaps[1].should eq((9..10))
194
+ end
195
+
196
+ it "should work even if ranges are out of order" do
197
+ gaps = (0..10).gaps([(2..3), (7..8), (4..6)])
198
+ gaps[0].should eq((0..1))
199
+ gaps[1].should eq((9..10))
200
+ end
201
+
202
+ it "should work even if ranges overlap" do
203
+ gaps = (0..10).gaps([(-2..3), (2..8), (4..10)])
204
+ gaps.should be_empty
205
+ end
206
+ end
207
+
208
+ describe "coverage overlaps" do
209
+ it "should return an empty array if ranges are empty" do
210
+ (0..10).overlaps([]).should be_empty
211
+ end
212
+
213
+ it "should return an empty array if ranges is same as self" do
214
+ (0..10).overlaps([(0..10)]).should be_empty
215
+ end
216
+
217
+ it "should return an empty array if ranges is wider than self" do
218
+ (0..10).overlaps([(-5..15)]).should be_empty
219
+ end
220
+
221
+ it "should return an empty array if ranges is narrower than self" do
222
+ (0..10).overlaps([(5..8)]).should be_empty
223
+ end
224
+
225
+ it "should return an array of overlaps" do
226
+ overlaps = (0..10).overlaps([(0..3), (2..6), (4..10)])
227
+ overlaps.size.should eq(2)
228
+ overlaps[0].should eq((2..3))
229
+ overlaps[1].should eq((4..6))
230
+ end
231
+
232
+ it "should not return any overlaps before self" do
233
+ overlaps = (0..10).overlaps([(-5..-3), (-4..-1), (0..3), (2..6), (4..10)])
234
+ overlaps.size.should eq(2)
235
+ overlaps[0].should eq((2..3))
236
+ overlaps[1].should eq((4..6))
237
+ end
238
+
239
+ it "should not return any overlaps after self" do
240
+ overlaps = (0..10).overlaps([(0..3), (2..6), (4..15), (11..20)])
241
+ overlaps.size.should eq(2)
242
+ overlaps[0].should eq((2..3))
243
+ overlaps[1].should eq((4..6))
244
+ end
245
+ end
246
+ end