Files
coder/enterprise/coderd/dormancy/dormantusersjob_test.go
2024-10-31 17:55:42 -05:00

116 lines
4.0 KiB
Go

package dormancy_test
import (
"context"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbmem"
"github.com/coder/coder/v2/enterprise/coderd/dormancy"
"github.com/coder/quartz"
)
func TestCheckInactiveUsers(t *testing.T) {
t.Parallel()
// Predefine job settings
interval := time.Millisecond
dormancyPeriod := 90 * 24 * time.Hour
// Add some dormant accounts
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
db := dbmem.New()
ctx, cancelFunc := context.WithCancel(context.Background())
t.Cleanup(cancelFunc)
inactiveUser1 := setupUser(ctx, t, db, "dormant-user-1@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(-time.Minute))
inactiveUser2 := setupUser(ctx, t, db, "dormant-user-2@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(-time.Hour))
inactiveUser3 := setupUser(ctx, t, db, "dormant-user-3@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(-6*time.Hour))
activeUser1 := setupUser(ctx, t, db, "active-user-1@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(time.Minute))
activeUser2 := setupUser(ctx, t, db, "active-user-2@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(time.Hour))
activeUser3 := setupUser(ctx, t, db, "active-user-3@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(6*time.Hour))
suspendedUser1 := setupUser(ctx, t, db, "suspended-user-1@coder.com", database.UserStatusSuspended, time.Now().Add(-dormancyPeriod).Add(-time.Minute))
suspendedUser2 := setupUser(ctx, t, db, "suspended-user-2@coder.com", database.UserStatusSuspended, time.Now().Add(-dormancyPeriod).Add(-time.Hour))
suspendedUser3 := setupUser(ctx, t, db, "suspended-user-3@coder.com", database.UserStatusSuspended, time.Now().Add(-dormancyPeriod).Add(-6*time.Hour))
mAudit := audit.NewMock()
mClock := quartz.NewMock(t)
// Run the periodic job
closeFunc := dormancy.CheckInactiveUsersWithOptions(ctx, logger, mClock, db, mAudit, interval, dormancyPeriod)
t.Cleanup(closeFunc)
dur, w := mClock.AdvanceNext()
require.Equal(t, interval, dur)
w.MustWait(ctx)
rows, err := db.GetUsers(ctx, database.GetUsersParams{})
require.NoError(t, err)
var dormant, suspended int
for _, row := range rows {
if row.Status == database.UserStatusDormant {
dormant++
} else if row.Status == database.UserStatusSuspended {
suspended++
}
}
// 9 users in total, 3 active, 3 dormant, 3 suspended
require.Len(t, rows, 9)
require.Equal(t, 3, dormant)
require.Equal(t, 3, suspended)
require.Len(t, mAudit.AuditLogs(), 3)
allUsers := ignoreUpdatedAt(database.ConvertUserRows(rows))
// Verify user status
expectedUsers := []database.User{
asDormant(inactiveUser1),
asDormant(inactiveUser2),
asDormant(inactiveUser3),
activeUser1,
activeUser2,
activeUser3,
suspendedUser1,
suspendedUser2,
suspendedUser3,
}
require.ElementsMatch(t, allUsers, expectedUsers)
}
func setupUser(ctx context.Context, t *testing.T, db database.Store, email string, status database.UserStatus, lastSeenAt time.Time) database.User {
t.Helper()
user, err := db.InsertUser(ctx, database.InsertUserParams{ID: uuid.New(), LoginType: database.LoginTypePassword, Username: uuid.NewString()[:8], Email: email})
require.NoError(t, err)
// At the beginning of the test all users are marked as active
user, err = db.UpdateUserStatus(ctx, database.UpdateUserStatusParams{ID: user.ID, Status: status})
require.NoError(t, err)
user, err = db.UpdateUserLastSeenAt(ctx, database.UpdateUserLastSeenAtParams{ID: user.ID, LastSeenAt: lastSeenAt})
require.NoError(t, err)
return user
}
func asDormant(user database.User) database.User {
user.Status = database.UserStatusDormant
return user
}
func ignoreUpdatedAt(rows []database.User) []database.User {
for i := range rows {
rows[i].UpdatedAt = time.Time{}
}
return rows
}