blob: cb7c038ef0421e7e9c65d5f55db6083b571c4331 [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001package matchers
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/onsi/gomega/format"
8)
9
10type BeTemporallyMatcher struct {
11 Comparator string
12 CompareTo time.Time
13 Threshold []time.Duration
14}
15
16func (matcher *BeTemporallyMatcher) FailureMessage(actual interface{}) (message string) {
17 return format.Message(actual, fmt.Sprintf("to be %s", matcher.Comparator), matcher.CompareTo)
18}
19
20func (matcher *BeTemporallyMatcher) NegatedFailureMessage(actual interface{}) (message string) {
21 return format.Message(actual, fmt.Sprintf("not to be %s", matcher.Comparator), matcher.CompareTo)
22}
23
24func (matcher *BeTemporallyMatcher) Match(actual interface{}) (bool, error) {
25 // predicate to test for time.Time type
26 isTime := func(t interface{}) bool {
27 _, ok := t.(time.Time)
28 return ok
29 }
30
31 if !isTime(actual) {
32 return false, fmt.Errorf("Expected a time.Time. Got:\n%s", format.Object(actual, 1))
33 }
34
35 switch matcher.Comparator {
36 case "==", "~", ">", ">=", "<", "<=":
37 default:
38 return false, fmt.Errorf("Unknown comparator: %s", matcher.Comparator)
39 }
40
41 var threshold = time.Millisecond
42 if len(matcher.Threshold) == 1 {
43 threshold = matcher.Threshold[0]
44 }
45
46 return matcher.matchTimes(actual.(time.Time), matcher.CompareTo, threshold), nil
47}
48
49func (matcher *BeTemporallyMatcher) matchTimes(actual, compareTo time.Time, threshold time.Duration) (success bool) {
50 switch matcher.Comparator {
51 case "==":
52 return actual.Equal(compareTo)
53 case "~":
54 diff := actual.Sub(compareTo)
55 return -threshold <= diff && diff <= threshold
56 case ">":
57 return actual.After(compareTo)
58 case ">=":
59 return !actual.Before(compareTo)
60 case "<":
61 return actual.Before(compareTo)
62 case "<=":
63 return !actual.After(compareTo)
64 }
65 return false
66}