blob: 918ee2840e6dfa77d4e55fe859ab8ce4be04fad0 [file] [log] [blame]
package assertions
import (
"fmt"
"time"
)
// ShouldHappenBefore receives exactly 2 time.Time arguments and asserts that the first happens before the second.
func ShouldHappenBefore(actual interface{}, expected ...interface{}) string {
if fail := need(1, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)
if !firstOk || !secondOk {
return shouldUseTimes
}
if !actualTime.Before(expectedTime) {
return fmt.Sprintf(shouldHaveHappenedBefore, actualTime, expectedTime, actualTime.Sub(expectedTime))
}
return success
}
// ShouldHappenOnOrBefore receives exactly 2 time.Time arguments and asserts that the first happens on or before the second.
func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) string {
if fail := need(1, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)
if !firstOk || !secondOk {
return shouldUseTimes
}
if actualTime.Equal(expectedTime) {
return success
}
return ShouldHappenBefore(actualTime, expectedTime)
}
// ShouldHappenAfter receives exactly 2 time.Time arguments and asserts that the first happens after the second.
func ShouldHappenAfter(actual interface{}, expected ...interface{}) string {
if fail := need(1, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)
if !firstOk || !secondOk {
return shouldUseTimes
}
if !actualTime.After(expectedTime) {
return fmt.Sprintf(shouldHaveHappenedAfter, actualTime, expectedTime, expectedTime.Sub(actualTime))
}
return success
}
// ShouldHappenOnOrAfter receives exactly 2 time.Time arguments and asserts that the first happens on or after the second.
func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) string {
if fail := need(1, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)
if !firstOk || !secondOk {
return shouldUseTimes
}
if actualTime.Equal(expectedTime) {
return success
}
return ShouldHappenAfter(actualTime, expectedTime)
}
// ShouldHappenBetween receives exactly 3 time.Time arguments and asserts that the first happens between (not on) the second and third.
func ShouldHappenBetween(actual interface{}, expected ...interface{}) string {
if fail := need(2, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
min, secondOk := expected[0].(time.Time)
max, thirdOk := expected[1].(time.Time)
if !firstOk || !secondOk || !thirdOk {
return shouldUseTimes
}
if !actualTime.After(min) {
return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, min.Sub(actualTime))
}
if !actualTime.Before(max) {
return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, actualTime.Sub(max))
}
return success
}
// ShouldHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first happens between or on the second and third.
func ShouldHappenOnOrBetween(actual interface{}, expected ...interface{}) string {
if fail := need(2, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
min, secondOk := expected[0].(time.Time)
max, thirdOk := expected[1].(time.Time)
if !firstOk || !secondOk || !thirdOk {
return shouldUseTimes
}
if actualTime.Equal(min) || actualTime.Equal(max) {
return success
}
return ShouldHappenBetween(actualTime, min, max)
}
// ShouldNotHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first
// does NOT happen between or on the second or third.
func ShouldNotHappenOnOrBetween(actual interface{}, expected ...interface{}) string {
if fail := need(2, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
min, secondOk := expected[0].(time.Time)
max, thirdOk := expected[1].(time.Time)
if !firstOk || !secondOk || !thirdOk {
return shouldUseTimes
}
if actualTime.Equal(min) || actualTime.Equal(max) {
return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max)
}
if actualTime.After(min) && actualTime.Before(max) {
return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max)
}
return success
}
// ShouldHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments)
// and asserts that the first time.Time happens within or on the duration specified relative to
// the other time.Time.
func ShouldHappenWithin(actual interface{}, expected ...interface{}) string {
if fail := need(2, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
tolerance, secondOk := expected[0].(time.Duration)
threshold, thirdOk := expected[1].(time.Time)
if !firstOk || !secondOk || !thirdOk {
return shouldUseDurationAndTime
}
min := threshold.Add(-tolerance)
max := threshold.Add(tolerance)
return ShouldHappenOnOrBetween(actualTime, min, max)
}
// ShouldNotHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments)
// and asserts that the first time.Time does NOT happen within or on the duration specified relative to
// the other time.Time.
func ShouldNotHappenWithin(actual interface{}, expected ...interface{}) string {
if fail := need(2, expected); fail != success {
return fail
}
actualTime, firstOk := actual.(time.Time)
tolerance, secondOk := expected[0].(time.Duration)
threshold, thirdOk := expected[1].(time.Time)
if !firstOk || !secondOk || !thirdOk {
return shouldUseDurationAndTime
}
min := threshold.Add(-tolerance)
max := threshold.Add(tolerance)
return ShouldNotHappenOnOrBetween(actualTime, min, max)
}
// ShouldBeChronological receives a []time.Time slice and asserts that they are
// in chronological order starting with the first time.Time as the earliest.
func ShouldBeChronological(actual interface{}, expected ...interface{}) string {
if fail := need(0, expected); fail != success {
return fail
}
times, ok := actual.([]time.Time)
if !ok {
return shouldUseTimeSlice
}
var previous time.Time
for i, current := range times {
if i > 0 && current.Before(previous) {
return fmt.Sprintf(shouldHaveBeenChronological,
i, i-1, previous.String(), i, current.String())
}
previous = current
}
return ""
}
// ShouldNotBeChronological receives a []time.Time slice and asserts that they are
// NOT in chronological order.
func ShouldNotBeChronological(actual interface{}, expected ...interface{}) string {
if fail := need(0, expected); fail != success {
return fail
}
if _, ok := actual.([]time.Time); !ok {
return shouldUseTimeSlice
}
result := ShouldBeChronological(actual, expected...)
if result != "" {
return ""
}
return shouldNotHaveBeenchronological
}