clonepack/internal/core/sync_test.go
GnomeZworc 9981373b83
fix error in code
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
2026-04-25 19:42:17 +02:00

268 lines
8.3 KiB
Go

package core_test
import (
"context"
"database/sql"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"github.com/syonad/clonepack/config"
"github.com/syonad/clonepack/internal/core"
"github.com/syonad/clonepack/internal/store"
)
// testEnv regroupe tous les stores + le SyncService câblé sur SQLite in-memory.
type testEnv struct {
db *sql.DB
repoStore *store.SQLiteRepoStore
pendingStore *store.SQLitePendingPackageStore
blockedStore *store.SQLiteBlockedPackageStore
snapshotStore *store.SQLiteSnapshotStore
cloneJobStore *store.SQLiteCloneJobStore
syncSvc *core.SyncService
snapshotSvc *core.SnapshotService
dataDir string
}
func newTestEnv(t *testing.T) *testEnv {
t.Helper()
db, err := store.Open(config.DBConfig{Path: ":memory:"})
if err != nil {
t.Fatalf("open db: %v", err)
}
t.Cleanup(func() { db.Close() })
dataDir := t.TempDir()
repoStore := store.NewRepoStore(db)
pendingStore := store.NewPendingPackageStore(db)
blockedStore := store.NewBlockedPackageStore(db)
snapshotStore := store.NewSnapshotStore(db)
cloneJobStore := store.NewCloneJobStore(db)
cloneSvc := core.NewCloneService(repoStore, cloneJobStore, dataDir)
snapshotSvc := core.NewSnapshotService(snapshotStore, repoStore, dataDir)
syncSvc := core.NewSyncService(repoStore, pendingStore, blockedStore, cloneSvc, snapshotSvc, dataDir)
return &testEnv{
db: db,
repoStore: repoStore,
pendingStore: pendingStore,
blockedStore: blockedStore,
snapshotStore: snapshotStore,
cloneJobStore: cloneJobStore,
syncSvc: syncSvc,
snapshotSvc: snapshotSvc,
dataDir: dataDir,
}
}
func (e *testEnv) createRepo(t *testing.T, name, repoType string) int64 {
t.Helper()
id, err := e.repoStore.CreateRepo(context.Background(), &store.Repo{
Name: name, Type: repoType, SourceURL: "https://example.com", SyncMode: "manual",
})
if err != nil {
t.Fatalf("createRepo %q: %v", name, err)
}
return id
}
func (e *testEnv) seedPending(t *testing.T, repoID int64, names ...string) []store.PendingPackage {
t.Helper()
pkgs := make([]store.PendingPackage, len(names))
for i, name := range names {
pkgs[i] = store.PendingPackage{
RepoID: repoID, Name: name, Version: "1.0", Arch: "amd64",
Location: "Packages/" + name + ".rpm", Checksum: "abc", ChecksumType: "sha256", Size: 100,
}
}
if err := e.pendingStore.UpsertPending(context.Background(), pkgs); err != nil {
t.Fatalf("seedPending: %v", err)
}
listed, _ := e.pendingStore.ListPending(context.Background(), repoID)
return listed
}
// --- ListPending ---
func TestSyncListPending(t *testing.T) {
env := newTestEnv(t)
repoID := env.createRepo(t, "rpm-repo", "rpm")
env.seedPending(t, repoID, "curl", "wget")
pkgs, err := env.syncSvc.ListPending(context.Background(), repoID)
if err != nil {
t.Fatalf("ListPending: %v", err)
}
if len(pkgs) != 2 {
t.Errorf("expected 2 pending, got %d", len(pkgs))
}
}
func TestSyncListPending_repoNotFound(t *testing.T) {
env := newTestEnv(t)
_, err := env.syncSvc.ListPending(context.Background(), 9999)
if err == nil {
t.Error("expected error for unknown repo")
}
}
// --- RejectPending ---
func TestRejectPending(t *testing.T) {
env := newTestEnv(t)
repoID := env.createRepo(t, "rpm-repo", "rpm")
listed := env.seedPending(t, repoID, "curl", "wget", "vim")
ids := []int64{listed[0].ID, listed[1].ID}
if err := env.syncSvc.RejectPending(context.Background(), repoID, ids); err != nil {
t.Fatalf("RejectPending: %v", err)
}
remaining, _ := env.pendingStore.ListPending(context.Background(), repoID)
if len(remaining) != 1 {
t.Fatalf("expected 1 remaining, got %d", len(remaining))
}
if remaining[0].Name != "vim" {
t.Errorf("expected vim remaining, got %q", remaining[0].Name)
}
}
// --- BlockPackages ---
func TestBlockPackages_removesFromPendingAndAddsToBlocked(t *testing.T) {
env := newTestEnv(t)
repoID := env.createRepo(t, "rpm-repo", "rpm")
listed := env.seedPending(t, repoID, "curl", "wget", "vim")
// Block curl and wget (by pending ID).
ids := []int64{listed[0].ID, listed[1].ID}
if err := env.syncSvc.BlockPackages(context.Background(), repoID, ids); err != nil {
t.Fatalf("BlockPackages: %v", err)
}
// Pending should only have vim left.
pending, _ := env.pendingStore.ListPending(context.Background(), repoID)
if len(pending) != 1 || pending[0].Name != "vim" {
t.Errorf("pending after block: expected [vim], got %v", pending)
}
// Blocked should have curl and wget.
blocked, _ := env.blockedStore.ListBlocked(context.Background(), repoID)
if len(blocked) != 2 {
t.Fatalf("blocked: expected 2, got %d", len(blocked))
}
names := map[string]bool{blocked[0].Name: true, blocked[1].Name: true}
if !names["curl"] || !names["wget"] {
t.Errorf("blocked names: got %v, want curl and wget", names)
}
}
// --- UnblockPackages ---
func TestUnblockPackages(t *testing.T) {
env := newTestEnv(t)
repoID := env.createRepo(t, "rpm-repo", "rpm")
listed := env.seedPending(t, repoID, "curl", "wget")
env.syncSvc.BlockPackages(context.Background(), repoID, []int64{listed[0].ID, listed[1].ID})
blocked, _ := env.blockedStore.ListBlocked(context.Background(), repoID)
if len(blocked) != 2 {
t.Fatalf("setup: expected 2 blocked, got %d", len(blocked))
}
if err := env.syncSvc.UnblockPackages(context.Background(), repoID, []int64{blocked[0].ID}); err != nil {
t.Fatalf("UnblockPackages: %v", err)
}
remaining, _ := env.blockedStore.ListBlocked(context.Background(), repoID)
if len(remaining) != 1 {
t.Fatalf("expected 1 blocked remaining, got %d", len(remaining))
}
}
// --- ApprovePending ---
func TestApprovePending_downloadsAndRemovesFromPending(t *testing.T) {
// Serve a fake package file.
const fileContent = "fake-rpm-content"
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fileContent))
}))
defer srv.Close()
env := newTestEnv(t)
ctx := context.Background()
// Repo with source URL pointing to our test server.
repoID, _ := env.repoStore.CreateRepo(ctx, &store.Repo{
Name: "rpm-repo", Type: "rpm", SourceURL: srv.URL, SyncMode: "manual",
})
// Initialise a proper RPM repo so RegenerateMetadata and TakeSnapshot succeed.
localDir := filepath.Join(env.dataDir, "repos", "1", "rpm")
buildRPMRepo(t, localDir, nil)
// Seed one pending package. Checksum left empty so verify is skipped.
pkg := store.PendingPackage{
RepoID: repoID, Name: "curl", Version: "7.88", Arch: "amd64",
Location: "Packages/curl.rpm", Checksum: "", ChecksumType: "sha256", Size: int64(len(fileContent)),
}
env.pendingStore.UpsertPending(ctx, []store.PendingPackage{pkg})
listed, _ := env.pendingStore.ListPending(ctx, repoID)
if err := env.syncSvc.ApprovePending(ctx, repoID, []int64{listed[0].ID}); err != nil {
t.Fatalf("ApprovePending: %v", err)
}
// Package must be removed from pending.
remaining, _ := env.pendingStore.ListPending(ctx, repoID)
if len(remaining) != 0 {
t.Errorf("expected empty pending after approve, got %d", len(remaining))
}
// File must exist on disk.
dest := filepath.Join(localDir, "Packages", "curl.rpm")
if _, err := os.Stat(dest); err != nil {
t.Errorf("expected file on disk at %s: %v", dest, err)
}
}
func TestApprovePending_continuesOnDownloadError(t *testing.T) {
// Server returns 404 for everything.
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
}))
defer srv.Close()
env := newTestEnv(t)
ctx := context.Background()
repoID, _ := env.repoStore.CreateRepo(ctx, &store.Repo{
Name: "rpm-repo", Type: "rpm", SourceURL: srv.URL, SyncMode: "manual",
})
env.pendingStore.UpsertPending(ctx, []store.PendingPackage{
{RepoID: repoID, Name: "curl", Version: "1.0", Arch: "amd64", Location: "pkg/curl.rpm", ChecksumType: "sha256"},
{RepoID: repoID, Name: "wget", Version: "1.0", Arch: "amd64", Location: "pkg/wget.rpm", ChecksumType: "sha256"},
})
listed, _ := env.pendingStore.ListPending(ctx, repoID)
ids := []int64{listed[0].ID, listed[1].ID}
// Should return errors but not panic.
err := env.syncSvc.ApprovePending(ctx, repoID, ids)
if err == nil {
t.Error("expected errors for 404 downloads, got nil")
}
// Nothing approved — pending should remain.
remaining, _ := env.pendingStore.ListPending(ctx, repoID)
if len(remaining) != 2 {
t.Errorf("expected 2 still pending, got %d", len(remaining))
}
}