132 lines
3.7 KiB
Go
132 lines
3.7 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func int64ptr(v int64) *int64 { return &v }
|
|
func boolptr(v bool) *bool { return &v }
|
|
|
|
func TestHostRepoStatsRoundTrip(t *testing.T) {
|
|
t.Parallel()
|
|
s := openTestStore(t)
|
|
ctx := context.Background()
|
|
|
|
const hostID = "h-stats-test"
|
|
seedHost(t, s, hostID)
|
|
|
|
// 1. Initial upsert: set TotalSizeBytes only.
|
|
if err := s.UpsertHostRepoStats(ctx, hostID, HostRepoStats{
|
|
TotalSizeBytes: int64ptr(100),
|
|
}); err != nil {
|
|
t.Fatalf("upsert 1: %v", err)
|
|
}
|
|
got, err := s.GetHostRepoStats(ctx, hostID)
|
|
if err != nil {
|
|
t.Fatalf("get after upsert 1: %v", err)
|
|
}
|
|
if got.TotalSizeBytes == nil || *got.TotalSizeBytes != 100 {
|
|
t.Errorf("TotalSizeBytes: want 100, got %v", got.TotalSizeBytes)
|
|
}
|
|
if got.LastCheckStatus != "" {
|
|
t.Errorf("LastCheckStatus should be empty after first upsert, got %q", got.LastCheckStatus)
|
|
}
|
|
|
|
// 2. Upsert with LastCheckStatus; TotalSizeBytes must be preserved.
|
|
if err := s.UpsertHostRepoStats(ctx, hostID, HostRepoStats{
|
|
LastCheckStatus: "ok",
|
|
}); err != nil {
|
|
t.Fatalf("upsert 2: %v", err)
|
|
}
|
|
got, err = s.GetHostRepoStats(ctx, hostID)
|
|
if err != nil {
|
|
t.Fatalf("get after upsert 2: %v", err)
|
|
}
|
|
if got.TotalSizeBytes == nil || *got.TotalSizeBytes != 100 {
|
|
t.Errorf("TotalSizeBytes should still be 100 after second upsert, got %v", got.TotalSizeBytes)
|
|
}
|
|
if got.LastCheckStatus != "ok" {
|
|
t.Errorf("LastCheckStatus: want %q, got %q", "ok", got.LastCheckStatus)
|
|
}
|
|
|
|
// 3. Upsert with LockPresent=true; all other fields preserved.
|
|
now := time.Now().UTC().Truncate(time.Second)
|
|
if err := s.UpsertHostRepoStats(ctx, hostID, HostRepoStats{
|
|
LockPresent: boolptr(true),
|
|
LastCheckAt: &now,
|
|
}); err != nil {
|
|
t.Fatalf("upsert 3: %v", err)
|
|
}
|
|
got, err = s.GetHostRepoStats(ctx, hostID)
|
|
if err != nil {
|
|
t.Fatalf("get after upsert 3: %v", err)
|
|
}
|
|
if got.LockPresent == nil || !*got.LockPresent {
|
|
t.Error("LockPresent should be true after upsert 3")
|
|
}
|
|
if got.TotalSizeBytes == nil || *got.TotalSizeBytes != 100 {
|
|
t.Errorf("TotalSizeBytes still 100 expected, got %v", got.TotalSizeBytes)
|
|
}
|
|
if got.LastCheckStatus != "ok" {
|
|
t.Errorf("LastCheckStatus still 'ok' expected, got %q", got.LastCheckStatus)
|
|
}
|
|
if got.LastCheckAt == nil {
|
|
t.Error("LastCheckAt should be set")
|
|
} else if !got.LastCheckAt.UTC().Truncate(time.Second).Equal(now) {
|
|
t.Errorf("LastCheckAt: got %v, want %v", got.LastCheckAt.UTC().Truncate(time.Second), now)
|
|
}
|
|
|
|
// 4. Clear lock (set to false).
|
|
if err := s.UpsertHostRepoStats(ctx, hostID, HostRepoStats{
|
|
LockPresent: boolptr(false),
|
|
}); err != nil {
|
|
t.Fatalf("upsert 4: %v", err)
|
|
}
|
|
got, err = s.GetHostRepoStats(ctx, hostID)
|
|
if err != nil {
|
|
t.Fatalf("get after upsert 4: %v", err)
|
|
}
|
|
if got.LockPresent == nil || *got.LockPresent {
|
|
t.Error("LockPresent should be false after upsert 4")
|
|
}
|
|
}
|
|
|
|
func TestHostRepoStatsNotFound(t *testing.T) {
|
|
t.Parallel()
|
|
s := openTestStore(t)
|
|
ctx := context.Background()
|
|
|
|
_, err := s.GetHostRepoStats(ctx, "no-such-host")
|
|
if !errors.Is(err, ErrNotFound) {
|
|
t.Errorf("expected ErrNotFound, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestHostRepoStatsCascadeDelete(t *testing.T) {
|
|
t.Parallel()
|
|
s := openTestStore(t)
|
|
ctx := context.Background()
|
|
|
|
const hostID = "h-cascade-test"
|
|
seedHost(t, s, hostID)
|
|
|
|
if err := s.UpsertHostRepoStats(ctx, hostID, HostRepoStats{
|
|
TotalSizeBytes: int64ptr(999),
|
|
}); err != nil {
|
|
t.Fatalf("upsert: %v", err)
|
|
}
|
|
|
|
// Delete the host; stats row should cascade-delete.
|
|
if _, err := s.DB().ExecContext(ctx,
|
|
`DELETE FROM hosts WHERE id = ?`, hostID); err != nil {
|
|
t.Fatalf("delete host: %v", err)
|
|
}
|
|
_, err := s.GetHostRepoStats(ctx, hostID)
|
|
if !errors.Is(err, ErrNotFound) {
|
|
t.Errorf("after host delete, expected ErrNotFound for stats; got %v", err)
|
|
}
|
|
}
|