| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 | package assertionsimport (	"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 ""}
 |