Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: unit test for getNextSchedule #518

Merged
merged 1 commit into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion controllers/csiaddons/reclaimspacecronjob_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,6 @@ func getScheduledTimeForRSJob(rsJob *csiaddonsv1alpha1.ReclaimSpaceJob) (*time.T
return &timeParsed, nil
}

// TODO: add unit test for getNextSchedule
// getNextSchedule returns lastMissed and next time after parsing the schedule.
// This function returns error if there are more than 100 missed start times.
func getNextSchedule(
Expand Down
104 changes: 104 additions & 0 deletions controllers/csiaddons/reclaimspacecronjob_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ package controllers

import (
"fmt"
"reflect"
"testing"
"time"

csiaddonsv1alpha1 "github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1"

"github.com/stretchr/testify/assert"
nixpanic marked this conversation as resolved.
Show resolved Hide resolved
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
)

func TestGetScheduledTimeForRSJob(t *testing.T) {
Expand Down Expand Up @@ -108,3 +110,105 @@ func TestGetScheduledTimeForRSJob(t *testing.T) {
})
}
}

func TestGetNextSchedule(t *testing.T) {
now := time.Now()
type args struct {
rsCronJob *csiaddonsv1alpha1.ReclaimSpaceCronJob
now time.Time
}
tests := []struct {
name string
args args
lastMissed time.Time
nextSchedule time.Time
wantErr bool
}{
{
name: "Valid schedule, no deadline, last schedule time exists",
args: args{
rsCronJob: &csiaddonsv1alpha1.ReclaimSpaceCronJob{
Spec: csiaddonsv1alpha1.ReclaimSpaceCronJobSpec{
Schedule: "0 0 * * *",
},
Status: csiaddonsv1alpha1.ReclaimSpaceCronJobStatus{
LastScheduleTime: &metav1.Time{Time: now.Add(-time.Hour)},
},
},
now: now,
},
lastMissed: time.Time{},
nextSchedule: time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).Add(time.Hour * 24),
wantErr: false,
},
{
name: "Valid schedule, deadline not exceeded, last schedule time exists",
args: args{
rsCronJob: &csiaddonsv1alpha1.ReclaimSpaceCronJob{
Spec: csiaddonsv1alpha1.ReclaimSpaceCronJobSpec{
Schedule: "0 0 * * *",
StartingDeadlineSeconds: ptr.To(int64(3600)),
},
Status: csiaddonsv1alpha1.ReclaimSpaceCronJobStatus{
LastScheduleTime: &metav1.Time{Time: now.Add(-time.Hour)},
},
},
now: now,
},
lastMissed: time.Time{},
nextSchedule: time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).Add(time.Hour * 24),
wantErr: false,
},
{
name: "Valid schedule, deadline exceeded, last schedule time exists, missed schedules < 100",
args: args{
rsCronJob: &csiaddonsv1alpha1.ReclaimSpaceCronJob{
Spec: csiaddonsv1alpha1.ReclaimSpaceCronJobSpec{
Schedule: "*/1 * * * *",
StartingDeadlineSeconds: ptr.To(int64(6000)),
},
Status: csiaddonsv1alpha1.ReclaimSpaceCronJobStatus{
LastScheduleTime: &metav1.Time{Time: now.Add(-time.Hour * 2)},
},
},
now: now,
},
lastMissed: time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, time.Local),
nextSchedule: time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, time.Local).Add(time.Minute),
wantErr: false,
},
{
name: "Valid schedule, deadline exceeded, last schedule time exists, missed schedules > 100",
args: args{
rsCronJob: &csiaddonsv1alpha1.ReclaimSpaceCronJob{
Spec: csiaddonsv1alpha1.ReclaimSpaceCronJobSpec{
Schedule: "*/1 * * * *",
StartingDeadlineSeconds: ptr.To(int64(6060)),
},
Status: csiaddonsv1alpha1.ReclaimSpaceCronJobStatus{
LastScheduleTime: &metav1.Time{Time: now.Add(-time.Hour * 2)},
},
},
now: now,
},
lastMissed: time.Time{},
nextSchedule: time.Time{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotLastMissed, gotNextSchedule, err := getNextSchedule(tt.args.rsCronJob, tt.args.now)
if (err != nil) != tt.wantErr {
t.Errorf("getNextSchedule() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotLastMissed, tt.lastMissed) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does getNextSchedule() always return an empty time.Time{} for lastMissed? Is there no reasonable way to test that it returns something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test for a valid lastMissed time as well now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, many thanks!

There are a lot of time.Now() calls that could have a little different time. Calling the 1st on 59.999 of a minute and the 2nd at 00.001 for example. Have you considered now = time.Now() and using now everywhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is a better approach to avoid any unwanted failures. Changed it accordingly.

t.Errorf("getNextSchedule() got last missed = %v, want %v", gotLastMissed, tt.lastMissed)
}
if !reflect.DeepEqual(gotNextSchedule, tt.nextSchedule) {
t.Errorf("getNextSchedule() got next schedule = %v, want %v", gotNextSchedule, tt.nextSchedule)
}
})
}
}
Loading