Skip to content

Commit

Permalink
Add support for overdue handling
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongjie-cai committed Mar 19, 2021
1 parent b39bb58 commit 55141d4
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 2,963 deletions.
3 changes: 2 additions & 1 deletion 0_functionPointers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,9 @@ func createMock(t *testing.T) {
}
updateScheduleIndexFuncExpected = 0
updateScheduleIndexFuncCalled = 0
updateScheduleIndexFunc = func(schedule *schedule) {
updateScheduleIndexFunc = func(schedule *schedule) bool {
updateScheduleIndexFuncCalled++
return false
}
generateFlagsDataFuncExpected = 0
generateFlagsDataFuncCalled = 0
Expand Down
38 changes: 25 additions & 13 deletions schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type schedule struct {
weekdays map[time.Weekday]bool
till *time.Time
timezone *time.Location
skipOverdue bool
completed bool
}

func moveValueIndex(
Expand Down Expand Up @@ -75,7 +77,7 @@ func constructTimeBySchedule(schedule *schedule) time.Time {

func updateScheduleIndex(
schedule *schedule,
) {
) bool {
var reset bool
// get next second from schedule data
schedule.second, schedule.secondIndex, reset = moveValueIndexFunc(
Expand Down Expand Up @@ -116,16 +118,19 @@ func updateScheduleIndex(
)
if reset {
// month reset, thus get next year from schedule data
schedule.year, schedule.yearIndex, _ = moveValueIndexFunc(
schedule.year, schedule.yearIndex, reset = moveValueIndexFunc(
schedule.yearIndex,
schedule.years,
9999, // hopefully nobody is still using this library by year 9999?
)
// reset on year means the whole schedule rotated to its beginning, thus meaning the schedule is completed
return reset
}
}
}
}
}
return false
}

func (schedule *schedule) NextSchedule() *time.Time {
Expand All @@ -135,16 +140,23 @@ func (schedule *schedule) NextSchedule() *time.Time {
// causes the schedule to terminate
return nil
}
// load next schedule time
var timeNext = constructTimeByScheduleFunc(
schedule,
)
if timeNext.Before(currentLocalTime) {
// in past means schedule has been reset, so no longer runnable
return nil
for {
if schedule.completed {
// causes the schedule to terminate
return nil
}
// load next schedule time
var timeNext = constructTimeByScheduleFunc(
schedule,
)
schedule.completed = updateScheduleIndexFunc(
schedule,
)
if currentLocalTime.Before(timeNext) {
return &timeNext
}
if !schedule.skipOverdue {
return &timeNext
}
}
updateScheduleIndexFunc(
schedule,
)
return &timeNext
}
152 changes: 142 additions & 10 deletions schedule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -860,14 +860,86 @@ func TestNextSchedule_ExceededTillTime(t *testing.T) {
verifyAll(t)
}

func TestNextSchedule_NextTimeInPast(t *testing.T) {
func TestNextSchedule_AlreadyCompleted(t *testing.T) {
// arrange
var dummyCurrentLocalTime = time.Now()

// mock
createMock(t)

// expect
timeNowExpected = 1
timeNow = func() time.Time {
timeNowCalled++
return dummyCurrentLocalTime
}

// SUT
var sut = &schedule{
completed: true,
}

// act
var result = sut.NextSchedule()

// assert
assert.Nil(t, result)

// verify
verifyAll(t)
}

func TestNextSchedule_NextInFuture(t *testing.T) {
// arrange
var dummyCurrentLocalTime = time.Now()
var dummySchedule = &schedule{}
var dummyTimeNext = dummyCurrentLocalTime.Add(1 * time.Second)
var dummyCompleted = rand.Intn(100) > 50

// mock
createMock(t)

// expect
timeNowExpected = 1
timeNow = func() time.Time {
timeNowCalled++
return dummyCurrentLocalTime
}
constructTimeByScheduleFuncExpected = 1
constructTimeByScheduleFunc = func(schedule *schedule) time.Time {
constructTimeByScheduleFuncCalled++
assert.Equal(t, dummySchedule, schedule)
return dummyTimeNext
}
updateScheduleIndexFuncExpected = 1
updateScheduleIndexFunc = func(schedule *schedule) bool {
updateScheduleIndexFuncCalled++
assert.Equal(t, dummySchedule, schedule)
return dummyCompleted
}

// SUT
var sut = dummySchedule

// act
var result = sut.NextSchedule()

// assert
assert.Equal(t, dummyTimeNext, *result)
assert.Equal(t, dummyCompleted, dummySchedule.completed)

// verify
verifyAll(t)
}

func TestNextSchedule_NextInPast_NoSkipOverdue(t *testing.T) {
// arrange
var dummyCurrentLocalTime = time.Now()
var dummyTill = dummyCurrentLocalTime.Add(1 * time.Second)
var dummySchedule = &schedule{
till: &dummyTill,
skipOverdue: false,
}
var dummyTimeNext = dummyCurrentLocalTime.Add(-1 * time.Second)
var dummyCompleted = rand.Intn(100) > 50

// mock
createMock(t)
Expand All @@ -884,6 +956,12 @@ func TestNextSchedule_NextTimeInPast(t *testing.T) {
assert.Equal(t, dummySchedule, schedule)
return dummyTimeNext
}
updateScheduleIndexFuncExpected = 1
updateScheduleIndexFunc = func(schedule *schedule) bool {
updateScheduleIndexFuncCalled++
assert.Equal(t, dummySchedule, schedule)
return dummyCompleted
}

// SUT
var sut = dummySchedule
Expand All @@ -892,20 +970,21 @@ func TestNextSchedule_NextTimeInPast(t *testing.T) {
var result = sut.NextSchedule()

// assert
assert.Nil(t, result)
assert.Equal(t, dummyTimeNext, *result)
assert.Equal(t, dummyCompleted, dummySchedule.completed)

// verify
verifyAll(t)
}

func TestNextSchedule_HappyPath(t *testing.T) {
func TestNextSchedule_NextInPast_SkipOverdue_Completed(t *testing.T) {
// arrange
var dummyCurrentLocalTime = time.Now()
var dummyTill = dummyCurrentLocalTime.Add(2 * time.Second)
var dummySchedule = &schedule{
till: &dummyTill,
skipOverdue: true,
}
var dummyTimeNext = dummyCurrentLocalTime.Add(1 * time.Second)
var dummyTimeNext = dummyCurrentLocalTime.Add(-1 * time.Second)
var dummyCompleted = true

// mock
createMock(t)
Expand All @@ -923,9 +1002,10 @@ func TestNextSchedule_HappyPath(t *testing.T) {
return dummyTimeNext
}
updateScheduleIndexFuncExpected = 1
updateScheduleIndexFunc = func(schedule *schedule) {
updateScheduleIndexFunc = func(schedule *schedule) bool {
updateScheduleIndexFuncCalled++
assert.Equal(t, dummySchedule, schedule)
return dummyCompleted
}

// SUT
Expand All @@ -935,7 +1015,59 @@ func TestNextSchedule_HappyPath(t *testing.T) {
var result = sut.NextSchedule()

// assert
assert.Equal(t, dummyTimeNext, *result)
assert.Nil(t, result)
assert.True(t, dummySchedule.completed)

// verify
verifyAll(t)
}

func TestNextSchedule_NextInPast_SkipOverdue_NotCompleted(t *testing.T) {
// arrange
var dummyCurrentLocalTime = time.Now()
var dummySchedule = &schedule{
skipOverdue: true,
}
var dummyTimeNextInPast = dummyCurrentLocalTime.Add(-1 * time.Second)
var dummyTimeNextInFuture = dummyCurrentLocalTime.Add(1 * time.Second)
var dummyCompleted = false

// mock
createMock(t)

// expect
timeNowExpected = 1
timeNow = func() time.Time {
timeNowCalled++
return dummyCurrentLocalTime
}
constructTimeByScheduleFuncExpected = 2
constructTimeByScheduleFunc = func(schedule *schedule) time.Time {
constructTimeByScheduleFuncCalled++
assert.Equal(t, dummySchedule, schedule)
if constructTimeByScheduleFuncCalled == 1 {
return dummyTimeNextInPast
} else if constructTimeByScheduleFuncCalled == 2 {
return dummyTimeNextInFuture
}
return time.Time{}
}
updateScheduleIndexFuncExpected = 2
updateScheduleIndexFunc = func(schedule *schedule) bool {
updateScheduleIndexFuncCalled++
assert.Equal(t, dummySchedule, schedule)
return dummyCompleted
}

// SUT
var sut = dummySchedule

// act
var result = sut.NextSchedule()

// assert
assert.Equal(t, dummyTimeNextInFuture, *result)
assert.False(t, dummySchedule.completed)

// verify
verifyAll(t)
Expand Down
Loading

0 comments on commit 55141d4

Please sign in to comment.