fat_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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