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 the 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 "" }