1package timespan
2
3import (
4	"testing"
5	"time"
6)
7
8var times = []time.Time{
9	time.Date(2014, time.February, 3, 2, 0, 0, 0, time.UTC),
10	time.Date(2014, time.February, 3, 4, 0, 0, 0, time.UTC),
11	time.Date(2014, time.February, 3, 6, 0, 0, 0, time.UTC),
12	time.Date(2014, time.February, 3, 8, 0, 0, 0, time.UTC),
13}
14
15var durations = []time.Duration{
16	time.Duration(2) * time.Hour,
17	time.Duration(4) * time.Hour,
18	time.Duration(6) * time.Hour,
19	time.Duration(-2) * time.Hour,
20}
21
22var spans = []Span{
23	New(times[0], durations[0]), // 2:00 - 4:00
24	New(times[0], durations[1]), // 2:00 - 6:00
25	New(times[0], durations[2]), // 2:00 - 8:00
26	New(times[1], durations[0]), // 4:00 - 6:00
27	New(times[1], durations[1]), // 4:00 - 8:00
28	New(times[2], durations[0]), // 6:00 - 8:00
29	New(times[1], durations[3]), // 2:00 - 4:00
30}
31
32func TestNew(t *testing.T) {
33	if spans[0].Start() != times[0] {
34		t.Error("Improper timespan start value.")
35	}
36	if spans[0].End() != times[1] {
37		t.Error("Improper timespan end value.")
38	}
39
40	if spans[6].Start() != times[0] {
41		t.Error("Improper timespan start value for negative duration.")
42	}
43	if spans[6].End() != times[1] {
44		t.Error("Improper timespan end value for negative duration.")
45	}
46}
47
48func TestAfter(t *testing.T) {
49	if spans[5].After(times[3]) { // 6:00 - 8:00 >? 8:00
50		t.Error("Span reported as after its end time.")
51	}
52	if spans[5].After(times[2]) { // 6:00 - 8:00 >? 6:00
53		t.Error("Span reported as after its start time.")
54	}
55	if !spans[5].After(times[1]) { // 6:00 - 8:00 >? 4:00
56		t.Error("Span reported as not after earlier time.")
57	}
58}
59
60func TestBefore(t *testing.T) {
61	if spans[0].Before(times[0]) { // 2:00 - 4:00 <? 2:00
62		t.Error("Span reported as before its start time.")
63	}
64	if spans[0].Before(times[1]) { // 2:00 - 4:00 <? 4:00
65		t.Error("Span reported as before its end time.")
66	}
67	if !spans[0].Before(times[2]) { // 2:00 - 4:00 <? 6:00
68		t.Error("Span reported as not before later time.")
69	}
70}
71
72func TestFollows(t *testing.T) {
73	if !spans[3].Follows(spans[0]) { // 4:00 - 6:00 >? 2:00 - 4:00
74		t.Error("Span reported as not following an earlier span.")
75	}
76	if spans[3].Follows(spans[1]) { // 4:00 - 6:00 >? 2:00 - 6:00
77		t.Error("Span reported as following a containing span ending at the same time.")
78	}
79	if spans[3].Follows(spans[3]) { // 4:00 - 6:00 >? 4:00 - 6:00
80		t.Error("Span reported as following itself.")
81	}
82	if spans[3].Follows(spans[4]) { // 4:00 - 6:00 >? 4:00 - 8:00
83		t.Error("Span reported as following a containing span ending at a later time.")
84	}
85	if spans[3].Follows(spans[5]) { // 4:00 - 6:00 >? 6:00 - 8:00
86		t.Error("Span reported as following a later span.")
87	}
88	if spans[2].Follows(spans[3]) { // 2:00 - 8:00 >? 4:00 - 6:00
89		t.Error("Span reported as following a fully contained span.")
90	}
91	if spans[4].Follows(spans[1]) { // 4:00 - 8:00 >? 2:00 - 6:00
92		t.Error("Span reported as following an overlapping span ending earlier.")
93	}
94	if spans[1].Follows(spans[4]) { // 2:00 - 6:00 >? 4:00 - 8:00
95		t.Error("Span reported as following an overlapping span ending later.")
96	}
97}
98
99func TestPrecedes(t *testing.T) {
100	if spans[3].Precedes(spans[0]) { // 4:00 - 6:00 <? 2:00 - 4:00
101		t.Error("Span reported as preceding an earlier span.")
102	}
103	if spans[3].Precedes(spans[1]) { // 4:00 - 6:00 <? 2:00 - 6:00
104		t.Error("Span reported as preceding a containing span starting earlier.")
105	}
106	if spans[3].Precedes(spans[3]) { // 4:00 - 6:00 <? 4:00 - 6:00
107		t.Error("Span reported as preceding itself.")
108	}
109	if spans[3].Precedes(spans[4]) { // 4:00 - 6:00 <? 4:00 - 8:00
110		t.Error("Span reported as preceding a containing span starting at the same time.")
111	}
112	if !spans[3].Precedes(spans[5]) { // 4:00 - 6:00 <? 6:00 - 8:00
113		t.Error("Span reported as not preceding a later span.")
114	}
115	if spans[2].Precedes(spans[3]) { // 2:00 - 8:00 <? 4:00 - 6:00
116		t.Error("Span reported as preceding a fully contained span.")
117	}
118	if spans[4].Precedes(spans[1]) { // 4:00 - 8:00 <? 2:00 - 6:00
119		t.Error("Span reported as preceding an overlapping span starting earlier.")
120	}
121	if spans[1].Precedes(spans[4]) { // 2:00 - 6:00 <? 4:00 - 8:00
122		t.Error("Span reported as preceding an overlapping span starting later.")
123	}
124}
125
126func TestEqual(t *testing.T) {
127	if !spans[3].Equal(spans[3]) { // 4:00 - 6:00 =? 4:00 - 6:00
128		t.Error("Span reported as not equal to itself.")
129	}
130	if spans[3].Equal(spans[2]) { // 4:00 - 6:00 =? 2:00 - 8:00
131		t.Error("Span reported as equal to a fully containing span.")
132	}
133	if spans[2].Equal(spans[3]) { // 2:00 - 8:00 =? 4:00 - 6:00
134		t.Error("Span reported as equal to a fully contained span.")
135	}
136	if spans[3].Equal(spans[1]) { // 4:00 - 6:00 <? 2:00 - 6:00
137		t.Error("Span reported as equal to span with different start time.")
138	}
139	if spans[3].Equal(spans[4]) { // 4:00 - 6:00 <? 4:00 - 8:00
140		t.Error("Span reported as equal to span with different end time.")
141	}
142	if spans[1].Equal(spans[4]) { // 2:00 - 6:00 =? 4:00 - 8:00
143		t.Error("Span reported as equal to overlapping span.")
144	}
145	if !spans[0].Equal(spans[6]) { // 2:00 - 4:00 =? 2:00 - 4:00
146		t.Error("Span reported as not equal.")
147	}
148}
149
150func TestBorders(t *testing.T) {
151	if spans[0].Borders(spans[0]) {
152		t.Error("Span borders itself.")
153	}
154	if spans[0].Borders(spans[1]) {
155		t.Error("Span borders an encompassing span.")
156	}
157	if spans[0].Borders(spans[5]) {
158		t.Error("Span borders a non-bordering separate span.")
159	}
160	if !spans[0].Borders(spans[3]) {
161		t.Error("Span does not border a bordering span.")
162	}
163	if !spans[3].Borders(spans[0]) {
164		t.Error("Span does not border a bordering span.")
165	}
166}
167
168func TestContainsTime(t *testing.T) {
169	if spans[4].ContainsTime(times[0]) {
170		t.Error("Span contains time preceding its start.")
171	}
172	if !spans[4].ContainsTime(times[1]) {
173		t.Error("Span does not contain start time.")
174	}
175	if !spans[4].ContainsTime(times[2]) {
176		t.Error("Span does not contain time in middle.")
177	}
178	if !spans[4].ContainsTime(times[3]) {
179		t.Error("Span does not contain end time.")
180	}
181}
182
183func TestContains(t *testing.T) {
184	if spans[4].Contains(spans[0]) {
185		t.Error("Span contains preceding span.")
186	}
187	if spans[4].Contains(spans[1]) {
188		t.Error("Span contains overlapping span.")
189	}
190	if !spans[4].Contains(spans[3]) {
191		t.Error("Span does not contain fully contained span.")
192	}
193	if !spans[4].Contains(spans[4]) {
194		t.Error("Span does not contain itself.")
195	}
196	if spans[1].Contains(spans[5]) {
197		t.Error("Span contains following span.")
198	}
199}
200
201func TestEncompass(t *testing.T) {
202	if spans[0].Encompass(spans[0]) != spans[0] {
203		t.Error("Span encompassing itself is not equal to identity.")
204	}
205	if spans[0].Encompass(spans[5]) != spans[2] {
206		t.Error("Span encompassing separate span does not contain both.")
207	}
208	if spans[0].Encompass(spans[1]) != spans[1] {
209		t.Error("Span encompassing an encompassing span is not equal to the encompassing span.")
210	}
211	if spans[2].Encompass(spans[3]) != spans[2] {
212		t.Error("Span encompassing a contained span is not equal to identity.")
213	}
214}
215
216func TestGap(t *testing.T) {
217	if !spans[0].Gap(spans[0]).IsZero() {
218		t.Error("Gap with self is not zero.")
219	}
220	if !spans[0].Gap(spans[1]).IsZero() {
221		t.Error("Gap with encompassing span is not zero.")
222	}
223	if spans[0].Gap(spans[5]) != spans[3] {
224		t.Error("Gap not properly generated.")
225	}
226	s := spans[0].Gap(spans[3])
227	if s.Start() != times[1] || s.End() != times[1] {
228		t.Error("Gap from bordering spans is not their border.")
229	}
230}
231
232func TestIntersection(t *testing.T) {
233	if _, b := spans[0].Intersection(spans[5]); b {
234		t.Error("Intersection of non-intersecting spans is not zero.")
235	}
236	if _, b := spans[0].Intersection(spans[3]); b {
237		t.Error("Intersection of bordering spans is not zero.")
238	}
239	if s, _ := spans[0].Intersection(spans[0]); s != spans[0] {
240		t.Error("Intersection with self is not identity.")
241	}
242	if s, _ := spans[0].Intersection(spans[2]); s != spans[0] {
243		t.Error("Intersection with encompassing span is not identity.")
244	}
245	if s, _ := spans[1].Intersection(spans[4]); s != spans[3] {
246		t.Error("Intersection improperly generated.")
247	}
248}
249
250func TestOffset(t *testing.T) {
251	if spans[0].Offset(durations[0]) != spans[3] {
252		t.Error("Offset created improper span.")
253	}
254	if spans[5].Offset(-durations[1]) != spans[0] {
255		t.Error("Negative offset created improper span.")
256	}
257	if spans[0].Offset(time.Duration(0)) != spans[0] {
258		t.Error("Zero offset does not result in identity.")
259	}
260}
261
262func TestOffsetDate(t *testing.T) {
263	s := New(times[0].AddDate(1, 1, 1), durations[0])
264	if spans[0].OffsetDate(1, 1, 1) != s {
265		t.Error("OffsetDate created improper span.")
266	}
267	s = New(times[0].AddDate(-1, -1, -1), durations[0])
268	if spans[0].OffsetDate(-1, -1, -1) != s {
269		t.Error("Negative OffsetDate created improper span.")
270	}
271	if spans[0].OffsetDate(0, 0, 0) != spans[0] {
272		t.Error("Zero OffsetDate does not result in identity.")
273	}
274}
275
276var (
277	d time.Duration
278	r Span
279	s Span
280	t time.Time
281)
282
283func BenchmarkStart(b *testing.B) {
284	s = spans[0]
285	for i := 0; i < b.N; i++ {
286		t = s.Start()
287	}
288}
289
290func BenchmarkEnd(b *testing.B) {
291	s = spans[0]
292	for i := 0; i < b.N; i++ {
293		t = s.End()
294	}
295}
296
297func BenchmarkDuration(b *testing.B) {
298	s = spans[0]
299	for i := 0; i < b.N; i++ {
300		d = s.Duration()
301	}
302}
303
304func BenchmarkAfter(b *testing.B) {
305	s = spans[5]
306	t = times[0]
307	for i := 0; i < b.N; i++ {
308		_ = s.After(t)
309	}
310}
311
312func BenchmarkBefore(b *testing.B) {
313	s = spans[5]
314	t = times[0]
315	for i := 0; i < b.N; i++ {
316		_ = s.Before(t)
317	}
318}
319
320func BenchmarkFollows(b *testing.B) {
321	s, r = spans[5], spans[0]
322	for i := 0; i < b.N; i++ {
323		_ = s.Follows(r)
324	}
325}
326
327func BenchmarkPrecedes(b *testing.B) {
328	s, r = spans[5], spans[0]
329	for i := 0; i < b.N; i++ {
330		_ = s.Precedes(r)
331	}
332}
333
334func BenchmarkContainsTime(b *testing.B) {
335	s = spans[2]
336	t = times[1]
337	for i := 0; i < b.N; i++ {
338		_ = s.ContainsTime(t)
339	}
340}
341
342func BenchmarkContains(b *testing.B) {
343	s, r = spans[2], spans[3]
344	for i := 0; i < b.N; i++ {
345		_ = s.Contains(r)
346	}
347}
348
349func BenchmarkEncompass(b *testing.B) {
350	s, r = spans[0], spans[5]
351	for i := 0; i < b.N; i++ {
352		_ = s.Encompass(r)
353	}
354}
355
356func BenchmarkGap(b *testing.B) {
357	s, r = spans[0], spans[5]
358	for i := 0; i < b.N; i++ {
359		_ = s.Gap(r)
360	}
361}
362
363func BenchmarkIntersection(b *testing.B) {
364	s, r = spans[1], spans[4]
365	for i := 0; i < b.N; i++ {
366		_, _ = s.Intersection(r)
367	}
368}
369
370func BenchmarkOffset(b *testing.B) {
371	s = spans[0]
372	d = durations[1]
373	for i := 0; i < b.N; i++ {
374		r = s.Offset(d)
375	}
376}
377
378func BenchmarkOffsetDate(b *testing.B) {
379	s = spans[0]
380	for i := 0; i < b.N; i++ {
381		r = s.OffsetDate(1, 1, 1)
382	}
383}
384
385func BenchmarkOverlaps(b *testing.B) {
386	s, r = spans[0], spans[1]
387	for i := 0; i < b.N; i++ {
388		_ = s.Overlaps(r)
389	}
390}
391
392func BenchmarkIsZero(b *testing.B) {
393	s = spans[0]
394	for i := 0; i < b.N; i++ {
395		_ = s.IsZero()
396	}
397}
398
399func BenchmarkEqual(b *testing.B) {
400	s, r = spans[0], spans[1]
401	for i := 0; i < b.N; i++ {
402		_ = s.Equal(r)
403	}
404}
405
406func BenchmarkBorders(b *testing.B) {
407	s, r = spans[0], spans[3]
408	for i := 0; i < b.N; i++ {
409		_ = s.Borders(r)
410	}
411}
412